使用组合框SelectedItem WPF MVVM(ItemsControl)绑定两个对象

时间:2017-08-09 11:04:21

标签: c# wpf mvvm combobox

我有一个问题列表(ItemsControl)。每个问题都有一个组合框,所有组合框都是相同的,想法是实现匹配的问题。 我想要的是能够绑定所选项目和选定的问题,所以我知道使用了哪个组合框。我无法弄清楚如何使用Combo Box,因为它不会采用可用于其他控件的命令。

<ItemsControl ItemsSource="{Binding Path=Question.QuestionResponses}" Grid.Row="1">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                </Grid.ColumnDefinitions>

                <WebBrowser Margin="0,6,0,6"
                            Grid.Column="0"
                            Unloaded="WebBrowserUnload"
                            util:WebBrowserBehaviors.Body="{Binding QuestionResponse.AnswerText}"></WebBrowser>
                <ComboBox Margin="0,6,0,6"
                          Grid.Column="1"
                          ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.Question.MatchesModel.Answers, Mode=OneWay}"
                          DisplayMemberPath="Answer">
                    <ComboBox.SelectedItem>
                        <MultiBinding Converter="{StaticResource MatchConverter}">
                            <Binding Path="."></Binding>
                            <Binding Path="."></Binding>
                        </MultiBinding>
                    </ComboBox.SelectedItem>
                </ComboBox>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

简而言之,我想将两个对象传递给我的model / viewModel,因此我可以处理选择。我已经尝试使用转换器来构造组合对象,但我不知道如何在使用多重绑定时为<ComboBox.SelectedItem>定义目标。任何帮助表示感谢,我在网上找不到任何东西。

编辑我有一个组合框列表,它可以是2或20个,具体取决于列表大小。每个组合框都有相同的项目来源。我可以绑定每个组合框的选定项目,但我无法知道用于选择项目的文本框。我需要知道控件的id,它包含组合框以识别它。我可以获取所选项目,我可以获得包含组合框的对象,我不能做的是将这两个值传递给我的模型/ viewmodel,这样我就可以将选择与适当的所有者ID绑定。组合框或其所有者的内容完全不相关我只想识别使用哪个组合框。我意识到我可以通过后面的代码来做到这一点,但我更喜欢mvvm方式,我可以复制项目源并包含控件,这是很多重复的数据,但可能会更容易保持选定的答案。

2 个答案:

答案 0 :(得分:0)

假设您有一个MatchItemViewModel类型的项目列表,并且对于每个项目,您都有一个描述文本SomeText,用户应从组合框中选择匹配的问题/答案/任何内容SelectedFromCombobox。匹配项和要在组合框中显示的可能值放在父视图模型ViewModel中:

public class ViewModel
{
    private ObservableCollection<MatchItemViewModel> _ListItems = new ObservableCollection<MatchItemViewModel>();
    public ObservableCollection<MatchItemViewModel> ListItems
    {
        get { return _ListItems; }
    }


    private ObservableCollection<string> _ComboboxItems = new ObservableCollection<string>();
    public ObservableCollection<string> ComboboxItems
    {
        get { return _ComboboxItems; }
    }
}


public class MatchItemViewModel : INotifyPropertyChanged
{

    private string _SomeText;
    public string SomeText
    {
        get { return _SomeText; }
        set { _SomeText = value; RaisePropertyChangedEvent(); }
    }


    private string _SelectedFromCombobox;
    public string SelectedFromCombobox
    {
        get { return _SelectedFromCombobox; }
        set { _SelectedFromCombobox = value; RaisePropertyChangedEvent(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChangedEvent([CallerMemberName]string prop = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(prop));
    }
}

对于我的测试,我在窗口构造函数中初始化数据如下:

public MainWindow()
{
    InitializeComponent();
    var vm = new ViewModel();
    vm.ListItems.Add(new MatchItemViewModel() { SomeText = "Red dogs are strange" });
    vm.ListItems.Add(new MatchItemViewModel() { SomeText = "I'm hungry" });
    vm.ComboboxItems.Add("What do you think of red dogs?");
    vm.ComboboxItems.Add("Current state of mind");

    grid1.DataContext = vm;
}

这是窗口内容XAML:

<Grid x:Name="grid1" Margin="2">
    <Grid.Resources>
        <CollectionViewSource x:Key="ComboBoxItemsSource" Source="{Binding ComboboxItems}"/>
    </Grid.Resources>
    <ItemsControl ItemsSource="{Binding ListItems}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"></ColumnDefinition>
                        <ColumnDefinition Width="Auto"></ColumnDefinition>
                    </Grid.ColumnDefinitions>

                    <TextBlock Text="{Binding SomeText}" MinWidth="100" VerticalAlignment="Center"/>
                    <ComboBox Margin="0,6,0,6"
                              Grid.Column="1"
                              ItemsSource="{Binding Source={StaticResource ComboBoxItemsSource}}"
                              IsSynchronizedWithCurrentItem="False"
                              SelectedItem="{Binding SelectedFromCombobox}">
                    </ComboBox>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

重要的是,为了使组合框项目可用于每个列表项,我在列表外创建了一个名为CollectionViewSource的{​​{1}},我在ComboBoxItemsSource中引用了这个集合。每个列表项。在组合框中设置{StaticResource ComboBoxItemsSource}也很重要,因为否则所有这些都会更新到相同的选定项目。

答案 1 :(得分:0)

如果其他人遇到类似这样的问题,你希望选择的语句与多个组合框中的选择相匹配,并且你想知道如何识别使用了哪个组合框。我通过为每个组合框提供模型列表来克服这个问题。通过这种方式,您可以存储语句的ID,如果您希望从数据库加载选择而不是仅存储选择项,它还可以更轻松地存储所选项目。

  public class QuestionMatchesModel :BaseModel
{
    public ObservableCollection<MatchOptions> Answers { get; set; }

    private MatchOptions _selected;

    public MatchOptions Selected
    {
        get => _selected;
        set
        {
            _selected = value;
            RaisePropertyChanged("Selection");
        }
    }
}

public class MatchOptions : BaseModel
{
    public long ResponseId { get; set; }
    public long MatchId { get; set; }
    public string Answer { get; set; }
}

}

示例可以使用的模型,为主模型中的每个语句创建一个列表。