将相同的Collection绑定到ComboBox和Datagrid

时间:2017-07-14 12:16:39

标签: c# .net wpf xaml prism

GitHub链接:https://github.com/babakin34/wpf_test/tree/master/WpfApp1

我有以下课程:

的ViewModels

public class PersonVM : BindableBase
{
  public int ID { get; set; }

  private string _lastName;
  public string LastName
  {
      get { return _lastName; }
      set { SetProperty(ref _lastName, value); }
  }
}

public class MainVM : BindableBase
{
  public ObservableCollection<PersonVM> People { get; set; }

  private PersonVM _selectedPerson;
  public PersonVM SelectedPerson
  {
      get { return _selectedPerson; }
      set { SetProperty(ref _selectedPerson, value); }
  }

  public MainVM()
  {
      People = new ObservableCollection<PersonVM>()
      {
          new PersonVM()
          {
              ID = 1,
              LastName = "AA"
          },
          new PersonVM()
          {
              ID = 2,
              LastName = "BB"
          },
      };

      SelectedPerson = People.First();
  }
}

查看

<小时/>                   

<Grid>
    <StackPanel>
        <ComboBox ItemsSource="{Binding People}" 
                  SelectedItem="{Binding SelectedPerson}"
                  DisplayMemberPath="LastName" 
                  Margin="0,5,0,25"/>

        <DataGrid ItemsSource="{Binding People}"/>
    </StackPanel>
</Grid>

当用户选择由Datagrid的默认最后一个条目引起的空元素时,如何实现ComboBox中的“MainVM.SelectedPerson”?

PS:我正在使用棱镜,但问题不在于棱镜相关。您可以通过INotifyPropertyChanged替换BindableBase。

1 个答案:

答案 0 :(得分:2)

编辑: 这里真正的问题与我最初想的有点不同。选择插入行时,您会在输出窗口中看到WPF无法强制转换&#34; NamedObject&#34;进入&#34; PersonVM&#34;。 Datagrid为要使用的插入行创建NamedObject,但绑定根本不起作用,因为它的类型错误。 简洁的解决方案是创建一个转换器来检查对象是否为PersonVM类型,否则返回null(而不是NamedObject实例)。

public class MyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is PersonVM)
            return value;
        return null;
    }
}

在xaml中

<DataGrid x:Name="DataGrid"
                  ItemsSource="{Binding People}"
                  SelectedCellsChanged="DataGrid_OnSelectedCellsChanged"
                  SelectedItem="{Binding SelectedPerson,
                                         Converter={StaticResource myConverter}}"

又旧又脏

不是最好的方式,但是如果你不介意在代码隐藏中使用视图模型(或通过接口抽象),你可以使用&#34; SelectionChanged&#34;如果任何所选项目不是您需要的类型,则将ViewModel中的SelectedPerson设置为null。

private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        bool invalidStuffSelected = false;
        //throw new System.NotImplementedException();
        foreach (var obj in DataGrid.SelectedItems)
        {
            if (!(obj is PersonVM))
                invalidStuffSelected = true;
        }
        MainVM vm = (MainVM) this.DataContext;
        if (invalidStuffSelected)
            vm.SelectedPerson = null;
    }

在你的例子中,selectionmode&#34; single&#34;因为组合框只能显示一个选定的值,所以会更有意义。