将ListView中的多个唯一UserControl绑定到ObservableCollection

时间:2013-02-17 08:46:59

标签: c# wpf listview mvvm-light observablecollection

我希望用户能够在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中的正确位置吗?

1 个答案:

答案 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应用程序中,然后自行查看结果。它看起来像这样:

enter image description here