如何在SilverLight中组合一些UserControl?

也许这是一个简单的问题,但我找不到答案。 我有三个用户控件,只有颜色不同。 其中有一个代码:

             

如何将它们组合成ObservableCollection Children?

 public class NodeViewModel : INotifyPropertyChanged { public ObservableCollection Children { get { return _children; } set { _children = value; NotifyChange("Children"); } } private void NotifyChange(string propName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propName)); } } 

我如何使用此控件集合的then元素?

这样做有简单(或正确的方法)吗?

据我所知,你有3个用户控件,其名称类似于NodePicture,GreenNodePicture和BlueNodePicture。 首先,如果3个控件的差异很小,那么最好只有一个控件使用某些属性值来切换颜色。

假设您的控件因canvas上矩形的背景颜色而异。 所以我会改变你的控制权:

       

我删除了Resources部分,因为视图不应该创建新的视图模型对象,它应该使用现有的DataContext。 您可以看到矩形的背景颜色基于视图模型的属性NodeColor 。 我们将此属性添加到视图模型:

 public class NodeViewModel : INotifyPropertyChanged { private SolidColorBrush _nodeColor; public SolidColorBrush NodeColor { get { return _nodeColor; } set { _nodeColor = value; NotifyChange("NodeColor"); } } //... 

现在,如果要显示3个不同颜色的控件,则应创建3个具有不同属性的视图模型。 以下是红色,蓝色和绿色视图模型的示例:

 public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); var redBrush = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0)); var greenBrush = new SolidColorBrush(Color.FromArgb(255, 0, 255, 0)); var blueBrush = new SolidColorBrush(Color.FromArgb(255, 0, 0, 255)); this.DataContext = new MainViewModel { Nodes = new ObservableCollection{ new NodeViewModel { NodeColor = redBrush, Children = new ObservableCollection{ new NodeViewModel { NodeColor = greenBrush, LeftOffset = 65, TopOffset = 10}, new NodeViewModel { NodeColor = greenBrush, LeftOffset = 55, TopOffset = 60} } }, //red new NodeViewModel { NodeColor = greenBrush}, //green new NodeViewModel { NodeColor = blueBrush} //blue } }; } } public class MainViewModel { public ObservableCollection Nodes { get; set; } } 

使用数据模板将视图模型转换为视图:

        

我没有使用Children属性,因为我不知道在哪里使用它。 也许子节点显示在canvas上。 无论如何,如果它很重要 – 你可以提供额外的信息,我会帮助你。

更新:

在canvas上绘制子项的最简单方法是添加依赖项属性,该属性在更新集合时更新canvas:

 public partial class NodePicture : UserControl { public NodePicture() { InitializeComponent(); } public IEnumerable ChildViewModels { get { return (IEnumerable)GetValue(ChildViewModelsProperty); } set { SetValue(ChildViewModelsProperty, value); } } public static readonly DependencyProperty ChildViewModelsProperty = DependencyProperty.Register("ChildViewModels", typeof(IEnumerable), typeof(NodePicture), new PropertyMetadata(null, (s, e) => ((NodePicture)s).UpdateCanvas())); private void UpdateCanvas() { this.ParentCanvas.Children.Clear(); var items = this.ChildViewModels; if(items == null) return; var controls = items.Select(item=> { var e = new Ellipse{Width = 20, Height = 20}; e.Fill = item.NodeColor; //Or using the data binding //BindingOperations.SetBinding(e, Ellipse.FillProperty, new Binding("NodeColor") { Source = item }); Canvas.SetLeft(e, item.LeftOffset); Canvas.SetTop(e, item.TopOffset); return e; }); foreach(var c in controls) this.ParentCanvas.Children.Add(c); } 

TopOffset和LeftOffset是NodeViewModel类的属性。 之后,您应该在xaml代码中设置此属性:

     

它不适用于ObservableColelction类,因为我没有处理CollectionChanged事件。 另一种方法 – 使用ListBox控件与自定义ItemsPanelTemplateListBoxItem ControlTemplate 。 但这是一个更复杂的解决方案。