[C#] क्या XAML में कैनवास के बच्चों की संपत्ति बाँधना संभव है?


Answers

<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>
Question

मैं थोड़ा आश्चर्यचकित हूं कि कैनवस के लिए बंधन स्थापित करना संभव नहीं है। 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>

क्या यह कोड-पीछे के दृष्टिकोण का उपयोग किए बिना पूरा करने का एक तरीका है? मैंने इस विषय पर कुछ गोगलिंग किया है, लेकिन इस विशिष्ट समस्या के लिए बहुत ज्यादा नहीं आया है।

मुझे अपना वर्तमान दृष्टिकोण पसंद नहीं है क्योंकि यह मेरा अच्छा मॉडल-व्यू-देखें मॉडेल को देखने के द्वारा इसे देखने के बारे में देखें मॉडेेल




ItemsControl कंट्रोल को अन्य संग्रहों से यूआई नियंत्रण के गतिशील संग्रह बनाने के लिए डिज़ाइन किया गया है, यहां तक ​​कि गैर-यूआई डेटा संग्रह भी।

आप एक Canvas पर आकर्षित करने के लिए एक ItemsControl को टेम्प्लेट कर सकते हैं। आदर्श तरीके से बैकिंग पैनल को एक Canvas में सेट करना होगा और फिर CanvasCanvas.Left और 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 संस्करण की तरह व्यवहार करता है। मैंने यह प्रदर्शित करने के लिए बनाया है कि आप अपने कस्टम क्लासेस का उपयोग कर सकते हैं।

एक अंतिम विवरण: आप चाहते हैं कि किसी भी संग्रह के लिए ItemsSource संपत्ति बाँध सकते हैं। उदाहरण के लिए:

<ItemsControls ItemsSource="{Binding Document.Items}"><!--etc, etc...-->

ItemsControl और यह कैसे काम करता है के बारे में अधिक जानकारी के लिए, इन दस्तावेजों की जांच करें: MSDN पुस्तकालय संदर्भ ; डेटा टेम्पलेटिंग ; मदोंकंट्रोल पर डॉ WPF की श्रृंखला