我怎么能结合在Silverlight用户控件的一些? [英] How can I combine some UserControls in SilverLight?

查看:127
本文介绍了我怎么能结合在Silverlight用户控件的一些?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

也许这是一个简单的问题,但我无法找到答案。
我有只与色彩三个不同的用户控件。有code其中之一:

Maybe it is a simple question, but I can’t find the answer. I have three User controls that are different only with colour. There is code one of them:

<UserControl x:Class="SilverlightApplication14.NodePicture"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:SilverlightApplication14">

    <UserControl.Resources>
        <local:NodeViewModel x:Key="Children"  />
    </UserControl.Resources>
    <Grid x:Name="LayoutRootNodePicture" Height="100" Width="100"
          HorizontalAlignment="Center"  DataContext="{Binding Source={StaticResource Children}, Path=Children}" >
        <Canvas x:Name="ParentCanvas" Background="White" Width="100" Height="100" >
            <Rectangle Fill="Yellow" Stroke="Blue" Width="100" Height="100"   >
                </Rectangle  >

        </Canvas>
        <Image HorizontalAlignment="Center"
                       Source="add.png"
                       Stretch="Fill"
                       Width="16"
                       VerticalAlignment="Top"
                       Margin="0,0,2,2"
                       Height="16" MouseLeftButtonDown="Image_MouseLeftButtonDown">
        </Image>
            </Grid>
</UserControl>

我怎样才能将它们合并的ObservableCollection孩子?

How can I combine them into ObservableCollection Children?

public class NodeViewModel : INotifyPropertyChanged
    {

public ObservableCollection<NodeViewModel> Children
        {
            get { return _children; }
            set
            {
                _children = value;
                NotifyChange("Children");
            }
        }

        private void NotifyChange(string propName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
}

我怎样可以用那么这个控件集合的元素?

是否有这样做的一个简单的(或正确的方式)的方式?

Is there a simple (or a right way ) way of doing this?

推荐答案

据我了解你的权利,你有哪些有名字像NodePicture,GreenNodePicture和BlueNodePicture 3用户控件。
首先,如果3控制不同的一个非常小的程度,这将是最好有使用一些属性值切换颜色只有一个控制。

As far as I understood you right, you have 3 user controls which have names something like NodePicture, GreenNodePicture and BlueNodePicture. First of all, if the 3 controls differ to a very little degree, it would be better to have only one control which switches the color using some property value.

让我们假设你通过控制在画布上的矩形背景颜色不同。所以,我会改变你的控制,因此:

Let's suppose that your controls differ by the background color of the rectangle on the canvas. So I would change your control so:

<Grid x:Name="LayoutRootNodePicture" Height="100" Width="100"
      HorizontalAlignment="Center">
    <Canvas x:Name="ParentCanvas" Background="{Binding NodeColor}" Width="100" Height="100" >
    </Canvas>
    <Image HorizontalAlignment="Center"
                   Source="add.png"
                   Stretch="Fill"
                   Width="16"
                   VerticalAlignment="Top"
                   Margin="0,0,2,2"
                   Height="16" MouseLeftButtonDown="Image_MouseLeftButtonDown">
    </Image>
</Grid>

我已经删除了资源部分因为视图不应该创建新的视图模型对象,它应该使用现有的DataContext。你可以看到,矩形的背景色是基于视图模型的财产 NodeColor
让我们将这个属性添加到浏览模式:

I've removed the Resources section because the view shouldn't create new view model objects, it should use an existing DataContext. You can see that the background color of the rectangle is based on the property NodeColor of the view model. Let's add this property to the view model:

public class NodeViewModel : INotifyPropertyChanged
{
    private SolidColorBrush _nodeColor;

    public SolidColorBrush NodeColor
    {
        get { return _nodeColor; }
        set
        {
            _nodeColor = value;
            NotifyChange("NodeColor");
        }
    }
    //...

现在,如果你想显示不同颜色的3控制你应该创建3个具有不同特性的视图模型。这里是红色,蓝色和绿色的ViewModels的示例:

And now if you want to display 3 controls with different color you should create 3 view models with different properties. Here is the example of the red, blue and green viewmodels:

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<NodeViewModel>{
                new NodeViewModel 
                { 
                    NodeColor = redBrush,
                    Children = new ObservableCollection<NodeViewModel>{
                        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<NodeViewModel> Nodes { get; set; }
}

查看模型使用数据模板翻译成观点:

View models are translated into the views using data templates:

<ListBox ItemsSource="{Binding Nodes}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <local:NodePicture DataContext="{Binding}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我没有使用过儿童的财产,因为我不明白的地方使用它。也许子节点都显示在画布上。无论如何,如果是重要的 - 你可以提供更多的信息,我会在这方面帮助

I haven't used the Children property because I haven't understood where to use it. Maybe child nodes are displayed on the canvas. Anyway if it is important - you can provide additional information and I'll help with this.

更新:

要在画布上绘制子项最简单的方法是添加哪些更新集合时更新画布的依赖属性:

The easiest way to draw child items on the canvas is to add the dependency property which updates the canvas when the collection is updated:

public partial class NodePicture : UserControl
{
    public NodePicture()
    {
        InitializeComponent();
    }

    public IEnumerable<NodeViewModel> ChildViewModels
    {
        get { return (IEnumerable<NodeViewModel>)GetValue(ChildViewModelsProperty); }
        set { SetValue(ChildViewModelsProperty, value); }
    }

    public static readonly DependencyProperty ChildViewModelsProperty =
        DependencyProperty.Register("ChildViewModels", typeof(IEnumerable<NodeViewModel>), 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和左偏移是NodeViewModel类的属性。
之后,你应该在XAML code设置此属性:

Where the TopOffset and LeftOffset are the properties of the NodeViewModel class. After that you should set this property in the xaml code:

    <DataTemplate>
        <local:NodePicture DataContext="{Binding}" ChildViewModels="{Binding Children}" />
    </DataTemplate>

它不会与 ObservableColelction 类的工作,因为我没有处理 Col​​lectionChanged 事件。
另一种方法 - 使用的ListBox 控制与自定义 ItemsPanelTemplate ListBoxItem的控件模板。但它是更复杂的解决方案。

It won't work with the ObservableColelction class because i didn't handle the CollectionChanged event. Another approach - to use the ListBox control with the custom ItemsPanelTemplate and ListBoxItem ControlTemplate. But it is the much more complex solution.

这篇关于我怎么能结合在Silverlight用户控件的一些?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆