簡體   English   中英

如何將畫布的孩子綁定到集合?

[英]How to bind a canvas' children to a collection?

我在其中一個控件中有一個畫布,隨着集合的增長/縮小,我想向其中添加/刪除子級。

我知道我可以這樣做:

<Canvas>
    <Canvas.Children>
        <Rectangle/>
        <TextBox/>
    </Canvas.Children>
</Canvas>

但是這些元素是靜態定義的。 我設想這樣的事情:

<Canvas>
    <Canvas.Children ItemsSource={Binding Path="ItemCollection", Converter="{StaticResource VisualConverter}}/>
</Canvas>

有沒有類似於我上面的代碼的東西,實際上可以工作嗎? 我知道其他帖子,例如本篇本篇,但是我看到這些答案(出於我的目的)的一個問題是,您失去了命名畫布並在后面的代碼中訪問它的能力:這是模板中的一個元素,因此超出范圍。

在顯示項目集合(並支持Binding)時,您應該考慮ItemsControl 在這種情況下,您可以將其ItemsPanel設置為一些包含Canvas ItemsPanelTemplate ,如下所示:

<ItemsControl ItemsSource="{Binding ItemCollection, 
                           Converter={StaticResource VisualConverter}}">
   <ItemsControl.ItemsPanel>
      <ItemsPanelTemplate>
          <Canvas/>
      </ItemsPanelTemplate>
   </ItemsControl.ItemsPanel>
</ItemsControl>

現在, ItemsControl就像Canvas其中包含一些動態子級集合。

更新

我懷疑您使用的是錯誤的方法。 不確定這些方法的必要性,以便您必須創建自定義Canvas並要求在代碼隱藏中輕松訪問它。 使用標准的Canvas將無法為Children屬性設置某些Binding,因為它是只讀的。 在這里,我為支持綁定的附加屬性而不是標准的非附加Children屬性介紹一個簡單的實現:

public static class CanvasService
{
    public static readonly DependencyProperty ChildrenProperty = DependencyProperty.RegisterAttached("Children", typeof(IEnumerable<UIElement>), typeof(CanvasService), new UIPropertyMetadata(childrenChanged));
    private static Dictionary<INotifyCollectionChanged, Canvas> references = new Dictionary<INotifyCollectionChanged, Canvas>();
    public static IEnumerable<UIElement> GetChildren(Canvas cv)
    {
        return cv.GetValue(ChildrenProperty) as IEnumerable<UIElement>;
    }
    public static void SetChildren(Canvas cv, IEnumerable<UIElement> children)
    {
        cv.SetValue(ChildrenProperty, children);
    }
    private static void childrenChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
    {
        var canvas = target as Canvas;
        repopulateChildren(canvas);
        var be = canvas.GetBindingExpression(ChildrenProperty);
        if (be != null)
        {
            var elements = (be.ResolvedSourcePropertyName == null ? be.ResolvedSource : be.ResolvedSource.GetType().GetProperty(be.ResolvedSourcePropertyName).GetValue(be.ResolvedSource)) as INotifyCollectionChanged;
            if (elements != null)
            {
                var cv = references.FirstOrDefault(i => i.Value == canvas);
                if (!cv.Equals(default(KeyValuePair<INotifyCollectionChanged,Canvas>)))
                     references.Remove(cv.Key);
                references[elements] = canvas;
                elements.CollectionChanged -= collectionChangedHandler;
                elements.CollectionChanged += collectionChangedHandler;
            }
        } else references.Clear();            
    }
    private static void collectionChangedHandler(object sender, NotifyCollectionChangedEventArgs e)
    {
        Canvas cv;
        if (references.TryGetValue(sender as INotifyCollectionChanged, out cv))
        {                
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    foreach (var item in e.NewItems) cv.Children.Add(item as UIElement);
                    break;
                case NotifyCollectionChangedAction.Remove:
                    foreach (var item in e.OldItems) cv.Children.Remove(item as UIElement);
                    break;
                case NotifyCollectionChangedAction.Reset:
                    repopulateChildren(cv);
                    break;
            }
        }
    }
    private static void repopulateChildren(Canvas cv)
    {
        cv.Children.Clear();
        var elements = GetChildren(cv);
        foreach (UIElement elem in elements){
            cv.Children.Add(elem);
        }
    }
}

在XAML中的用法

<Canvas local:CanvasService.Children="{Binding ItemCollection, 
                                  Converter={StaticResource VisualConverter}}"/>

同樣,我認為您應該考慮另一種方法。 您應該在ItemsControl周圍有一些解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM