XAML에서 Canvas's Children 속성을 바인딩할 수 있습니까?
캔버스의 바인딩을 설정할 수 없는 것에 조금 놀랐습니다.XAML을 사용하는 아이들입니다. 저는 다음과 같은 코드 비하인드 접근법에 의지해야 했습니다.
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
DesignerViewModel dvm = this.DataContext as DesignerViewModel;
dvm.Document.Items.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Items_CollectionChanged);
foreach (UIElement element in dvm.Document.Items)
designerCanvas.Children.Add(element);
}
private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
ObservableCollection<UIElement> collection = sender as ObservableCollection<UIElement>;
foreach (UIElement element in collection)
if (!designerCanvas.Children.Contains(element))
designerCanvas.Children.Add(element);
List<UIElement> removeList = new List<UIElement>();
foreach (UIElement element in designerCanvas.Children)
if (!collection.Contains(element))
removeList.Add(element);
foreach (UIElement element in removeList)
designerCanvas.Children.Remove(element);
}
XAML에서 다음과 같이 바인딩을 설정하는 것이 좋습니다.
<Canvas x:Name="designerCanvas"
Children="{Binding Document.Items}"
Width="{Binding Document.Width}"
Height="{Binding Document.Height}">
</Canvas>
코드 비하인드 접근법에 의존하지 않고 이를 달성할 수 있는 방법이 있습니까?나는 그 주제에 대해 몇 가지 검색해 보았지만, 이 특정한 문제에 대해 많은 것을 생각해내지 못했다.
View가 ViewModel을 인식하도록 함으로써 모델-View-ViewModel을 망칠 수 있기 때문에 현재의 접근 방식이 마음에 들지 않습니다.
<ItemsControl ItemsSource="{Binding Path=Circles}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="White" Width="500" Height="500" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Fill="{Binding Path=Color, Converter={StaticResource colorBrushConverter}}" Width="25" Height="25" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
<Setter Property="Canvas.Left" Value="{Binding Path=X}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
다른 사람들은 여러분이 실제로 하고 싶은 일을 하는 방법에 대해 확장 가능한 답변을 했습니다.왜 묶지 못했는지 설명해줄게Children
직접적으로.
문제는 매우 간단합니다. 데이터 바인딩 대상은 읽기 전용 속성일 수 없습니다.Panel.Children
읽기 전용입니다.수집품에 대한 특별한 취급은 없습니다.그에 반해서,ItemsControl.ItemsSource
는 읽기/쓰기 속성입니다.다만, 수집 타입이지만, 에서는 드물게 발생합니다.NET 클래스. 단, 바인딩 시나리오를 지원하기 위해 필요합니다.
ItemsControl
는 다른 컬렉션(UI 이외의 데이터 수집도 포함)에서 UI 컨트롤의 동적 컬렉션을 작성하도록 설계되어 있습니다.
템플릿을 만들 수 있습니다.ItemsControl
끌어당기다Canvas
이상적인 방법은 백킹 패널을Canvas
그 후, 을 설정합니다.Canvas.Left
그리고.Canvas.Top
재산에 대한 정보를 수집합니다.이 작업을 수행할 수 없었습니다.ItemsControl
아이들을 용기로 싸서 세팅하는 것은 어렵다.Canvas
이러한 컨테이너의 속성.
대신, 저는Grid
모든 아이템을 위한 통으로, 각각의 아이템을 각각 그립니다.Canvas
이 방법에는 약간의 오버헤드가 있습니다.
<ItemsControl x:Name="Collection" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:MyPoint}">
<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Ellipse Width="10" Height="10" Fill="Black" Canvas.Left="{Binding X}" Canvas.Top="{Binding Y}"/>
</Canvas>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
소스 컬렉션을 설정하는 데 사용한 코드는 다음과 같습니다.
List<MyPoint> points = new List<MyPoint>();
points.Add(new MyPoint(2, 100));
points.Add(new MyPoint(50, 20));
points.Add(new MyPoint(200, 200));
points.Add(new MyPoint(300, 370));
Collection.ItemsSource = points;
MyPoint
커스텀 클래스입니다.System
버전입니다.독자적인 커스텀 클래스를 사용할 수 있다는 것을 증명하기 위해서 작성했습니다.
마지막 세부사항:아이템을 바인드할 수 있습니다.원하는 컬렉션에 속성을 제공합니다.예를 들어 다음과 같습니다.
<ItemsControls ItemsSource="{Binding Document.Items}"><!--etc, etc...-->
Items Control에 대한 자세한 내용과 그 구조에 대한 자세한 내용은 MSDN 라이브러리 레퍼런스, 데이터 템플릿 작성, Dr. WPF on ItemsControl 시리즈를 참조하십시오.
internal static class CanvasAssistant
{
#region Dependency Properties
public static readonly DependencyProperty BoundChildrenProperty =
DependencyProperty.RegisterAttached("BoundChildren", typeof (object), typeof (CanvasAssistant),
new FrameworkPropertyMetadata(null, onBoundChildrenChanged));
#endregion
public static void SetBoundChildren(DependencyObject dependencyObject, string value)
{
dependencyObject.SetValue(BoundChildrenProperty, value);
}
private static void onBoundChildrenChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs e)
{
if (dependencyObject == null)
{
return;
}
var canvas = dependencyObject as Canvas;
if (canvas == null) return;
var objects = (ObservableCollection<UIElement>) e.NewValue;
if (objects == null)
{
canvas.Children.Clear();
return;
}
//TODO: Create Method for that.
objects.CollectionChanged += (sender, args) =>
{
if (args.Action == NotifyCollectionChangedAction.Add)
foreach (object item in args.NewItems)
{
canvas.Children.Add((UIElement) item);
}
if (args.Action == NotifyCollectionChangedAction.Remove)
foreach (object item in args.OldItems)
{
canvas.Children.Remove((UIElement) item);
}
};
foreach (UIElement item in objects)
{
canvas.Children.Add(item);
}
}
}
사용방법:
<Canvas x:Name="PART_SomeCanvas"
Controls:CanvasAssistant.BoundChildren="{TemplateBinding SomeItems}"/>
Children 속성에서 바인딩을 사용할 수 없다고 생각합니다.사실 오늘 그렇게 하려고 했는데 너처럼 잘못됐어.
캔버스는 아주 기본적인 컨테이너입니다.이건 정말 이런 종류의 일을 위해 설계되지 않았어요.여러 항목 컨트롤 중 하나를 확인해야 합니다.ViewModel의 관찰 가능한 데이터 모델 컬렉션을 해당 항목에 바인딩할 수 있습니다.속성을 소스화하고 DataTemplates를 사용하여 각 항목이 컨트롤에서 렌더링되는 방법을 처리합니다.
항목을 만족스럽게 렌더링하는 ItemsControl을 찾을 수 없는 경우 필요한 작업을 수행하는 사용자 지정 컨트롤을 만들어야 할 수도 있습니다.
언급URL : https://stackoverflow.com/questions/889825/is-it-possible-to-bind-a-canvass-children-property-in-xaml
'source' 카테고리의 다른 글
치명적 오류: 클래스에 구현되지 않은 이니셜라이저 'init(코더:)'을 사용합니다. (0) | 2023.04.16 |
---|---|
cmd.exe에서 사용하는 인코딩/코드 페이지는 무엇입니까? (0) | 2023.04.16 |
XlsxWriter 개체는 Django에서 다운로드를 생성하기 위해 http 응답으로 저장됩니다. (0) | 2023.04.16 |
WPF MVVM 패턴을 사용한 뷰 탐색 (0) | 2023.04.16 |
,,,또는 SVG 파일의 경우?또는 SVG 파일의 경우?,,, , 「」 , 「」 , 「」 파일을 SVG 하는 . 파일을 SVG 하는 . 파일을 SVG 하는 .,,, ★★★★★★★★★★★★★★★★★」 ★★★★★★★★★★★.. (0) | 2023.04.16 |