2017-07-14 25 views
0

GitHub的链接:https://github.com/babakin34/wpf_test/tree/master/WpfApp1绑定同一收集到的ComboBox和DataGrid

我有以下类别:

的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(); 
    } 
} 

VIEW


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

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


我怎样才能做到这一点从ComboBox中“MainVM.SelectedPerson”当用户选择了空元素,这是由DataGrid的默认最后一个条目引起的通知?

PS:我使用棱镜,但问题不是棱镜相关。你可以用INotifyPropertyChanged替换BindableBase。

+0

您应该将“SelectedItem =”{Binding SelectedPerson}“''添加到DataGrid中 –

+0

您可以将DataGrid的CanUserAddRows属性设置为false以删除最后一个空行。这不是一个可以在ComboBox中选择的实际PersonVM,而是一个用于将新项目添加到DataGrid的占位符... – mm8

+0

@ mm8:我需要DataGrid的最后一行,以便用户可以添加新条目。 –

回答

2

编辑: 这里的真正问题与我一开始想的有点不同。在选择插入行时,您会在输出窗口中看到WPF无法将“NamedObject”转换为“PersonVM”。 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}}" 


旧又脏

不是最好的方式,但如果你不介意使用的视图模型(或抽象它通过一个接口)在代码隐藏中可以使用“SelectionChanged”事件来将ViewModel中的SelectedPerson设置为null f任何选定的项目都不是您需要的类型。

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

在你的例子中,选择模式“single”会更有意义,因为combobox只能显示一个选定的值。

+0

我已经用类似的方法解决了它。我只想知道,如果不使用代码背后的代码或任何肮脏的黑客行为是可能的。 –

+0

请看看我上面编辑的答案 – manni

相关问题