【问题标题】:WPF MVVM Binding collection to DataTemplateWPF MVVM 绑定集合到 DataTemplate
【发布时间】:2018-04-06 15:39:05
【问题描述】:

我有一个 ViewModel,它有一个 ObservableCollection<MyData> MainCollectionMyData SelectedData,其中包含 MainCollection 中当前选定的项目。 MyData 由几个属性和一个ObservableCollection<MyValuePair> MyPairs 组成。 MyValuePair 由 2 个属性 DescriptionValue 组成,就像 KeyValuePair 一样(不能使用字典,因为我想要双向绑定)。

我想根据我的 DataTemplate 为每个 MyValuePair 动态创建控件(我正在尝试这样做:Adding controls dynamically in WPF MVVM):

        //do not want to create another viewModel
        <DataTemplate DataType="{x:Type vm:MyValuePairViewModel }">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            //problem can only select one MyValuePair at a time
            <TextBlock Text="{Binding MyValuePair.Description, Mode=TwoWay}"/>
            <TextBox Template="{StaticResource TextBoxBaseControlTemplate}" Grid.Row="0" Grid.Column="1" Text="{Binding MyValuePair.Value, Mode=TwoWay}"/>
        </Grid>
    </DataTemplate>

我的数据:

public class MyData
{
    //Properties
    ObservableCollection<MyValuePair> MyPairs { get; set; }
}

主视图模型:

public class MainViewModel : ViewModelBase
{
    ObservableCollection<MyData> MainCollection { get; set; }

    MyData selectedData
    public MyData SelectedData
    {
        get { return selectedData; }
        set
        {
            Set(() => SelectedData, ref selectedData, value);
        }
    }
}

我的值对:

public class MyValuePair
{
    private string description;
    public string Description
    {
        get { return description; }
        set { description = value; }
    }

    private string _value;
    public string Value
    {
        get { return _value; }
        set { _value = value; }
    }

但问题是我不想为我的MyValuePair 创建另一个 ViewModel (MyValuePairViewModel),因为这样我必须在每次 SelectedData 更改或 MyPair(MyValuePair 类型)更改时将其与我的 MainViewModel 同步我必须将其同步回 MainViewModel,感觉不对。

那么有没有一种简单的方法可以将我的 DataTemplate 直接绑定到 SelectedData 中 ObservableCollection&lt;MyValuePair&gt; 属性内的每个元素,以便为每个 MyPairs 创建 DataTemplate?


编辑 目前我正在使用另一个 ViewModel:

public class MyValuePairViewModel : ViewModelBase
{
    private MyValuePair myValuePair;
    public MyValuePair MyValuePair
    {
        get { return myPair; }
        set
        {
            Set(() => MyValuePair, ref myValuePair, value);
        }
    }

    public MyValuePairViewModel(MyValuePair myValuePair)
    {
        MyValuePair = myValuePair;
    }
}

并将其添加到我的 MainViewModel 中,如下所示:
public ObservableCollection&lt;MyValuePairViewModel&gt; MyPairs { get; set; }.
因此,对于 MyPairs 中的每个元素,我都会创建上面的 DataTemplate

每当 ListView 的选择发生变化时,我都会执行以下操作:

public void RefreshKeyValuePairs()
    {
        if (MyPairs != null)
        {
            MyPairs.Clear();
        }

        if (SelectedData != null)
        {
            foreach (MyValuePair item in SelectedData.MyPairs)
            {
                MyValuePairViewModel vm = new MyValuePairViewModel(item);
                MyPairs.Add(vm);
            }
        }
    }

但是,在这种情况下,每当我在创建的 TextBox 内键入内容时,它不会仅在 MyValuePairViewModel 内的 MainViewModel 的 SelectedData 内更新,我必须在 MyValuePairViewModel Set 方法内手动将其同步到 MainViewModel 的 SelectedData(但这也需要我在 MyValuePairViewModel 中有 MainViewModel 的实例)。

换句话说,我想直接绑定到创建的元素 SelectedData.MyPairs[0].Description 绑定到第一个创建的 TextBlock,SelectedData.MyPairs[1].Description 绑定到第二个创建的 TextBlock 等等,以便它在两个方向上自动更新。如果SelectedData.MyPairs 不是集合而是普通属性,我可以直接绑定到它。

【问题讨论】:

  • 我并没有真正理解这个问题。使用类似这样的列表框将每个项目模板化到您的 itemtemplate 中的控件中。也许答案是使用当前项绑定 / 并在列表框上设置 IsSynchronizedWithCurrentItem true。绑定到 observablecollection 的默认视图。
  • 我认为您应该更改数据模板中的绑定。使用描述代替 SelectedData.MyPairs.Description,并对 Value 属性执行相同操作
  • @Andy 试图澄清一下。
  • WPF 博士构建了一种称为可观察字典的东西。我认为这确实有两种方式。我已经有一段时间没有使用了。 drwpf.com/blog/2007/09/16/can-i-bind-my-itemscontrol-to-a-dictionary/

标签: c# wpf mvvm binding observablecollection


【解决方案1】:

您可以将您的 UI 元素直接绑定到 MyValuePair 对象。您不需要特定的 ViewModel 类 MyValuePairViewModel。

您会错过的唯一一件事是 INotifyPropertyChanged 在 MyValuePair 上的实现。 UI 将正常初始化,但初始化后对 Description 和 Value 属性的编程更新不会出现在 UI 中。 如果您不进行任何程序化更新,这将不是问题。

如果您要更改 Description 和 Value 属性,最简单的方法是直接在 MyValuePair 上实现 INotifyPropertyChanged。 这只需要几行代码,并且比使用单独的 MyValuePairViewModel 类复制功能更容易。

【讨论】:

  • 我无法正确绑定(它只显示字符串而不是带有绑定文本的控件)。目前我有&lt;ItemsControl ItemsSource="{Binding SelectedData.MyPairs}"/&gt;I 并将DataTemplate 的绑定更改为DescriptionValue(删除MyValuePair.)。我也不明白的是,当我不使用 MyValuePairViewModel 时,我在 DataTemplate 中使用什么作为目标类型?
  • 现在我在 DataTemplate 中只使用了模型 m:MyValuePair,它可以工作,但我仍在为 SelectedData.MyPairs 中的每个 ValuePair 创建 MyValuePairViewModel 的实例。虽然它有效,但我不确定它是否是您建议将其直接绑定到 UI 的方式。
  • 但我认为我更喜欢将它绑定到 viewModel(模型保持干净),但我不喜欢 DataTemplate 的绑定与模型 m:MyValuePair 一起使用,但不适用于viewModel vm:MyValuePairViewModel(我使用了DescriptionValuePair.Description)。为什么?是因为MyPairs 的类型是MyValuePair 而不是MyValuePairViewModel
猜你喜欢
  • 2018-07-16
  • 1970-01-01
  • 1970-01-01
  • 2018-10-25
  • 2013-05-29
  • 1970-01-01
  • 2011-03-01
  • 2012-04-27
  • 1970-01-01
相关资源
最近更新 更多