我希望用户能够在10个或更多个唯一的UserControl之间进行选择,并以任意顺序在列表中以任意数量的任何UserControl的多个实例显示它们。因此,列表可能看起来像UC1,UC1,UC3,UC3,UC 10,UC8等。重要的是要注意前面示例中的两个UC1和两个UC3是具有与它们相关联的不同值的不同实例。从本质上讲,我正在创建一系列命令,我将其解析为真实世界的动作。
问题:我无法将ListView中显示的UserControl绑定到ObservableCollection中的数据。至少,我在UserControls中的绑定是错误的,我不知道如何让它们工作。
我正在使用MVVMLight。我有一个Window控件,只包含一个内容控件,其中加载了一个名为CommandView的UserControl,这是我的主显示器。 CommandView当前有几个按钮,其属性绑定到CommandViewModel中的中继命令,这些命令将唯一的类实例添加到名为CommandsCollection的ObservableCollection中。 ListView绑定到封装CommandsCollection的属性。
我在后面的代码中使用DataTemplate和DataTemplateSelector,根据集合中该位置的类的类型选择正确的UserControl(UC1,UC2等)。我有成功的工作,但我没有将显示的UserControl文本框绑定回ObservableCollection,因此UserControl的文本框中没有显示任何数据。我在ObservableCollection中设置类属性的默认值,并将集合写入文本文件,并查看值是默认值。所以ObservableCollection正在看到值。
如何在用户控件中设置绑定?这是我在UC1用户控件中的内容:
<lightext:UserControl
DataContext="{Binding VelocityCommandStatic, Source={StaticResource Locator}}">
<TextBox Text="{Binding VelocityCommandProperty.VelocityKinematic,
UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
VelocityCommandStatic - 我实际上也有点困惑,但这是在viewmodellocator.cs中创建的usercontrol的对象(?)。
绑定的最佳方式是什么? xaml绑定点可以直接返回ObservableCollection吗?一个问题是,每个UserControl都有不同的属性,我为集合中的每个用户控件放置了一个不同的类(实例)。我会知道属性,但需要在xaml中正确设置它们。也许这种方法并不理想。我可以在viewModel中将UserControl点的属性返回到CommandViewViewModel中observablecolleciton中的正确位置吗?
答案 0 :(得分:2)
看,你太复杂了。您只需要一个ObservableCollection,它可以保存您的所有项目以及每个项目的正确DataTemplate。不需要DataTemplateSelectors或任何其他类似的东西。此外,没有必要point directly back to the ObservableCollection
,无论这意味着什么:
主窗口:
<Window x:Class="WpfApplication5.Window3"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication5"
Title="Window3" Height="300" Width="300">
<Window.Resources>
<DataTemplate DataType="{x:Type local:Item1}">
<local:UserControl1/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Item2}">
<local:UserControl2/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Item3}">
<local:UserControl3/>
</DataTemplate>
</Window.Resources>
<ListBox ItemsSource="{Binding}"/>
</Window>
代码背后:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.ComponentModel;
namespace WpfApplication5
{
public partial class Window3 : Window
{
public Window3()
{
InitializeComponent();
DataContext = new ObservableCollection<ItemBase>
{
new Item1() {MyText1 = "This is MyText1 inside an Item1"},
new Item2() {MyText2 = "This is MyText2 inside an Item2"},
new Item3() {MyText3 = "This is MyText3 inside an Item3", MyBool = true}
};
}
}
public class ItemBase: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChange(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Item1: ItemBase
{
private string _myText1;
public string MyText1
{
get { return _myText1; }
set
{
_myText1 = value;
NotifyPropertyChange("MyText1");
}
}
}
public class Item2: ItemBase
{
private string _myText2;
public string MyText2
{
get { return _myText2; }
set
{
_myText2 = value;
NotifyPropertyChange("MyText2");
}
}
private ObservableCollection<string> _options;
public ObservableCollection<string> Options
{
get { return _options ?? (_options = new ObservableCollection<string>()); }
}
public Item2()
{
Options.Add("Option1");
Options.Add("Option2");
Options.Add("Option3");
Options.Add("Option4");
}
}
public class Item3: ItemBase
{
private string _myText3;
public string MyText3
{
get { return _myText3; }
set
{
_myText3 = value;
NotifyPropertyChange("MyText3");
}
}
private bool _myBool;
public bool MyBool
{
get { return _myBool; }
set
{
_myBool = value;
NotifyPropertyChange("MyBool");
}
}
}
}
的UserControl1:
<UserControl x:Class="WpfApplication5.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Border BorderBrush="Black" BorderThickness="1">
<StackPanel>
<TextBlock Text="This is UserControl1"/>
<TextBlock Text="{Binding MyText1}"/>
</StackPanel>
</Border>
</UserControl>
UserControl2:
<UserControl x:Class="WpfApplication5.UserControl2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Border BorderBrush="Black" BorderThickness="1">
<StackPanel>
<TextBlock Text="This is UserControl2"/>
<TextBox Text="{Binding MyText2}"/>
<ComboBox ItemsSource="{Binding Options}" SelectedItem="{Binding MyText2}"/>
</StackPanel>
</Border>
</UserControl>
UserControl3:
<UserControl x:Class="WpfApplication5.UserControl3"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Border BorderBrush="Black" BorderThickness="1">
<StackPanel>
<TextBlock Text="This is UserControl3"/>
<TextBlock Text="{Binding MyText3}"/>
<CheckBox Content="This is the MyBool Property" IsChecked="{Binding MyBool}"/>
</StackPanel>
</Border>
</UserControl>
只需将我的代码复制并粘贴到文件 - 新建 - WPF应用程序中,然后自行查看结果。它看起来像这样: