gpt4 book ai didi

c# - 我如何在 SilverLight 中组合一些用户控件?

转载 作者:太空宇宙 更新时间:2023-11-03 14:11:49 24 4
gpt4 key购买 nike

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

<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 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));
}
}

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

是否有一种简单(或正确的方法)可以做到这一点?

最佳答案

就我对您的理解而言,您有 3 个用户控件,它们的名称类似于 NodePicture、GreenNodePicture 和 BlueNodePicture。首先,如果 3 个控件的差异很小,那么最好只有一个控件使用某个属性值来切换颜色。

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

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

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

public class NodeViewModel : INotifyPropertyChanged
{
private SolidColorBrush _nodeColor;

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

现在如果你想用不同的颜色显示 3 个控件,你应该创建 3 个具有不同属性的 View 模型。这是红色、蓝色和绿色 View 模型的示例:

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 模型转换为 View :

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

我没有使用过 Children 属性,因为我不明白在哪里使用它。也许子节点显示在 Canvas 上。无论如何,如果它很重要 - 您可以提供更多信息,我会提供帮助。

更新:

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

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 和 LeftOffset 是 NodeViewModel 类的属性。之后,您应该在 xaml 代码中设置此属性:

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

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

关于c# - 我如何在 SilverLight 中组合一些用户控件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7578899/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com