2017-08-09 119 views
0

我有一个列表(ItemsControl)的问题。每个问题都有一个组合框,所有组合框都是相同的,想法是实现匹配问题。 我想要的是能够绑定选定的项目和选定的问题,所以我知道哪个组合框被使用。我不知道如何使用组合框做到这一点,因为它不接受可用于其他控件的命令。用组合框绑定两个对象SelectedItem WPF MVVM(ItemsControl)

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

总之,我想传递两个对象到我的模型/ viewModel,所以我可以处理选择。我尝试过使用转换器来构造组合对象,但我不知道如何在使用多重绑定时定义<ComboBox.SelectedItem>的目标。任何帮助表示赞赏,我在网上找不到任何东西。

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

+0

所以,如果我正确理解你,你有一个答案和问题列表的列表。你在'ItemsControl'中显示答案列表,并希望用户为每个答案选择正确的问题? – grek40

+0

是的,更准确地说,它的问题陈述和用户必须从组合框中选择正确的陈述/答案。问题是我不知道如何使用mvvm将它绑定回来。我可以绑定一个选择,但如果我不知道它属于哪个问题/声明,那对我来说并不好。所以我需要一种方法来传回问题对象来获得它的ID –

+0

也许你正在寻找'''',但我没有完全明白你的问题。 –

回答

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

}

范例模型可以使用,创建一个列表出来的这对你的主模型中的每个语句。

0

让假设你有MatchItemViewModel类型的项目列表,并对每个项目,你有一个说明文字SomeText,用户应该选择一个匹配的问题/答案/无论从ComboBox到财产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在列表的外部名为ComboBoxItemsSource,并且我在每个列表项中通过{StaticResource ComboBoxItemsSource}引用此集合。此外,在组合框中设置IsSynchronizedWithCurrentItem="False"也很重要,因为否则它们将始终更新为相同的选定项目。

+0

您如何知道使用了哪个组合框?我需要将选定的答案与其所有者相关联。这将让我选择的项目,所有组合框,但从我看到它仍然不知道哪一个是它。 –

+0

@AistisTaraskevicius你的意思是使用哪个组合框?我认为所有的组合框都有相同的内容。重要的部分是:每当进行选择时,调用一个特定“MatchItemViewModel”的'SelectedFromCombobox'设置程序,并将其与特定的'SomeText'完全链接到一个特定项目。如果你无法从那么多的信息中识别出你的物品,那么你就会遇到完全不同的问题。 – grek40

+0

想象一下,我有一张有人头的照片,头号显示鼻子,2号显示眼睛,3号显示嘴巴等等。然后你有一个问题,要求你将声明和数字联系起来。头是和用户预期的数量,嘴是,眼睛是。所以我需要知道哪个选择属于哪个选择。 –