使用代理时如何从ComboBox中获取SelectedItem?

时间:2019-05-10 06:11:32

标签: c# wpf xaml mvvm combobox

我正在使用Entity Framework和MVVM Light模式构建DataGrid,因此将Datagrid绑定到ListCollectionView就像这样:


    <DataGrid Grid.ColumnSpan="2" ItemsSource="{Binding RequestsModelView, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"
    SelectedItem="{Binding SelectedRequest, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">

ViewModel:

public ListCollectionView RequestsModelView { get; set; }
        public Requests RequestsModel
        {
            get => RequestsModelView?.CurrentItem as Requests;
            set
            {
                RequestsModelView?.MoveCurrentTo(value);
                RaisePropertyChanged();
            }
        }
        private void InitializeRequestsView()
        {
            RequestsModelView = CollectionViewSource.GetDefaultView(RequestsCollection) as ListCollectionView;

            RequestsModelView.CurrentChanged += (s, e) =>
            {
                RaisePropertyChanged(() => RequestsModel);
            };
        }

当我使用此Requests-ListColletionView中的属性(即Requests-table Entity中的值)时,这非常完美。 现在,我想添加一个DataGrid ComboBox,它从另一个表(即Requests_Functions-table Entity)中获取其值。我设法使其与代理一起使用(取自https://thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/)。这是XAML代码:


    <DataGridTemplateColumn  
                                        <DataGridTemplateColumn.CellTemplate>
                                            <DataTemplate>
                                                <TextBlock Text="{Binding Requests_Functions.Name, UpdateSourceTrigger=PropertyChanged}"/>
                                            </DataTemplate>
                                        </DataGridTemplateColumn.CellTemplate>
                                        <DataGridTemplateColumn.CellEditingTemplate>
                                            <DataTemplate>
                                                <ComboBox ItemsSource="{Binding Path=Data.FunctionNamesCollection, Source={StaticResource proxy}, UpdateSourceTrigger=PropertyChanged}"
                                                            SelectedItem="{Binding Requests_Functions.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged }" 
                                                          />
                                            </DataTemplate>
                                        </DataGridTemplateColumn.CellEditingTemplate>

                                    </DataGridTemplateColumn>

我现在的问题是,我不知道如何在ViewModel中正确获取SelectedItem(Requests_Functions.Name),因为它是一个相关表,而不是直接来自ListCollectionView-Entity。 有人知道如何获取SelectedItem吗?我尝试使用RowEditEnding EventTrigger,但始终遇到这样的问题,即SelectedItem与ListCollectionView-Entity不相同。

谢谢!

1 个答案:

答案 0 :(得分:0)

您是否尝试过使用IValueConverter在组合框列表中的对象类型和数据网格中的对象的相应属性之间进行转换-将其添加到ComboBox的SelectedItem绑定中? / p>

绑定应仅是:

<... SelectedItem="{Binding Name, Mode... etc., Converter={StaticResource myConverter}" >

下面的简单示例显示了其工作原理:

  public partial class MainWindow : Window
  {
    public MainWindow()
    {
      InitializeComponent();
    }
  }

  public class AllNamesProvider 
  {
    public AllNamesProvider()
    {
      AllNames = new ObservableCollection<Name>
      {
        new Name { FirstName = "aaaa", LastName = "AAAA" },
        new Name { FirstName = "bbbb", LastName = "BBBB" },
        new Name { FirstName = "cccc", LastName = "CCCC" },
        new Name { FirstName = "dddd", LastName = "DDDD" },
        new Name { FirstName = "eeee", LastName = "EEEE" },
        new Name { FirstName = "ffff", LastName = "FFFF" },
      };
    }


    public ObservableCollection<Name> AllNames
    {
      get;
    }
  }

  public class Name : INotifyPropertyChanged
  {
    private string m_firstName;
    public string FirstName
    {
      get { return m_firstName; }
      set
      {
        m_firstName = value;
        OnPropertyChanged("FirstName");
      }
    }

    private string m_lastName;
    public string LastName
    {
      get { return m_lastName; }
      set
      {
        m_lastName = value;
        OnPropertyChanged("LastName");
      }
    }

    private void OnPropertyChanged(string v)
    {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(v));
    }

    public event PropertyChangedEventHandler PropertyChanged;
  }

  public class Person : INotifyPropertyChanged
  {
    private int m_id;
    public int Id
    {
      get { return m_id; }
      set
      {
        m_id = value;
        OnPropertyChanged("Id");
      }
    }

    private string m_name;
    public string Name
    {
      get { return m_name; }
      set
      {
        m_name = value;
        OnPropertyChanged("Name");
      }
    }


    private void OnPropertyChanged(string v)
    {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(v));
    }

    public event PropertyChangedEventHandler PropertyChanged;
  }


  public class ViewModel
  {
    public ViewModel()
    {
      Persons = new ListCollectionView(new List<Person>
      {
        new Person { Id = 1, Name = "AAAA"},
        new Person { Id = 2, Name = "BBBB"},
        new Person { Id = 3, Name = "CCCC"},
      });
    }


    public ListCollectionView Persons { get; set; }

    void RaisePropertyChanged()
    {

    }
  }

使用NameConverter

  public class NameConverter : 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)
    {
      return (value as Name).LastName;
    }
  }

这是XAML:

  <Window.Resources>
    <local:AllNamesProvider x:Key="NamesProvider" />
    <local:NameConverter x:Key="NameConverter" />
  </Window.Resources>
  <Window.DataContext>
    <local:ViewModel />
  </Window.DataContext>
    <Grid>
    <Grid.RowDefinitions>
      <RowDefinition />
      <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <DataGrid Grid.ColumnSpan="2" AutoGenerateColumns="False" ItemsSource="{Binding Persons, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" >
      <DataGrid.Columns>
        <DataGridTextColumn Header="Id" Binding="{Binding Id}" Width="100"/>
        <DataGridTextColumn Header="Name1" Binding="{Binding Name}" Width="200" />
        <DataGridTemplateColumn Header="Name2" Width="200">
          <DataGridTemplateColumn.CellTemplate>
          <DataTemplate>
            <TextBlock Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/>
          </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
          <DataGridTemplateColumn.CellEditingTemplate>
            <DataTemplate>
              <ComboBox ItemsSource="{Binding Path=AllNames, Source={StaticResource ResourceKey=NamesProvider}}"                        
                        DisplayMemberPath="LastName"
                        SelectedItem="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource NameConverter}}" />
            </DataTemplate>
          </DataGridTemplateColumn.CellEditingTemplate>

        </DataGridTemplateColumn>
      </DataGrid.Columns>
    </DataGrid>
    <ComboBox 
      ItemsSource="{StaticResource ResourceKey=NamesProvider}"
      DisplayMemberPath="LastName"
      Grid.Row="1" />
  </Grid>

只需在Visual Studio中创建一个默认的WPF项目,然后将以上内容粘贴到MainWindow文件中即可。