【问题标题】:Binding multiple unique UserControls in a ListView to an ObservableCollection将 ListView 中的多个唯一用户控件绑定到 ObservableCollection
【发布时间】:2013-02-17 08:46:59
【问题描述】:

我希望用户能够在 10 个或更多唯一的用户控件之间进行选择,并以任意顺序将它们显示在一个列表中,其中包含任意数量的任何用户控件的多个实例。因此,列表可能如下所示 UC1、UC1、UC3、UC3、UC 10、UC8 等。需要注意的是,前面示例中的两个 UC1 和两个 UC3 是具有不同关联值的不同实例。本质上,我正在创建一系列命令,并将其解析为真实世界的动作。

问题:我无法将 ListView 中显示的 UserControls 绑定到 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 中创建的用户控件的对象(?)。

什么是最好的绑定方式? xaml 绑定点可以直接回到 ObservableCollection 吗?一个问题是,每个 UserControl 都有不同的属性,我为集合中的每个用户控件放置了不同的类(实例)。我会知道这些属性,但需要在 xaml 中正确设置它们。也许这种方法并不理想。我可以在视图模型中将 UserControl 的属性指向 CommandViewViewModel 中 observablecolleciton 中的正确位置吗?

【问题讨论】:

    标签: c# wpf listview mvvm-light observablecollection


    【解决方案1】:

    听着,你把事情复杂化了。您所需要的只是一个 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");
                }
            }
        }
    }
    

    用户控件1:

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

    用户控件2:

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

    用户控件3:

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

    【讨论】:

    • 我复制了你的代码并让它工作 - 你是对的,我确实让它过于复杂。我尽量不说我花了多少时间研究我的非工作解决方案,但它是大量的。这真的很棒 - 我非常感谢 - 谢谢!我会把它编织到我的程序中并尝试一下。
    猜你喜欢
    • 1970-01-01
    • 2012-10-23
    • 2012-05-26
    • 2018-05-21
    • 2017-09-29
    • 1970-01-01
    • 2015-09-02
    相关资源
    最近更新 更多