将 ComboBox ItemsSource 和 SelectedItem 绑定到不同的 DataContexts

问题描述 投票:0回答:1

在我的应用程序中,我有一个对象

MaterialLibrary
保存各种材料名称的列表,以及一个对象
UserInputData
保存各种用户输入。
MaterialLibrary
UserInputData
是并且应该是完全独立的对象。

目的是从属性

ComboBox
(
MaterialLibrary.MaterialNames
) 填充
ObservableCollection<string>
,并且用户选择的任何材料都会写入
UserInputData.SelectedMaterialName
(实现了
string
NotifyPropertyChanged
)。

第一部分意味着托管此

DataContext
Page
ComboBox
应该将其 DataContext 设置如下:

public partial class MaterialSelectionPage : Page
{
    public MaterialSelectionPage(MaterialLibrary matLib)
    {
        InitializeComponent();
        this.DataContext = matLib;
    }
}

ComboBox 应该这样定义:

<ComboBox x:Name="MaterialSelectionComboBox" ItemsSource="{Binding Path=MaterialNames}"/>

但是,第二部分意味着

DataContext
应该这样设置:

public partial class MaterialSelectionPage : Page
{
    public MaterialSelectionPage(UserInputData inputData)
    {
        InitializeComponent();
        this.DataContext = inputData;
    }
}

因此

ComboBox
的定义应该是:

<ComboBox x:Name="MaterialSelectionComboBox" SelectedItem="{Binding Path=SelectedMaterialName}"/>

这两个要求显然是相互冲突的,因为

MaterialSelectionPage
以及扩展后的
ComboBox
只能有一个
DataContext
。在这个例子中,我没有看到使用单个模型的任何简单方法,因为
MaterialLibrary
UserInputData
需要是完全独立的对象,并且在另一个内部引用一个模型是没有意义的。

任何人都可以建议实现此意图的正确方法是什么?

c# wpf data-binding
1个回答
2
投票

您可以创建一个类包装器,其中包含

MaterialLibrary
UserInputData
的实例作为属性。然后将该包装器提供给视图并设置为 DataContext。

例如:

public class MultipleDataContextWrapper
{
    public MaterialLibrary MatLibInstance { get; }
    public UserInputData InputDataInstance { get; }

    public MultipleDataContextWrapper()
    {
        // Initialize instances in some way
    }
}

然后将该包装器提供给视图:

public partial class MaterialSelectionPage : Page
{
    public MaterialSelectionPage(MultipleDataContextWrapper dataContextWrapper)
    {
        InitializeComponent();
        this.DataContext = dataContextWrapper;
    }
}

并在 XAML 中访问包装实例的属性作为包装器属性的子属性:

<ComboBox x:Name="MaterialSelectionComboBox" 
          ItemsSource="{Binding Path=MatLibInstance.MaterialNames}"
          SelectedItem="{Binding Path=InputDataInstance.SelectedMaterialName}"/>
© www.soinside.com 2019 - 2024. All rights reserved.