Как получить SelectedItem из ComboBox при использовании прокси? - PullRequest
0 голосов
/ 10 мая 2019

Я строю DataGrid с Entity Framework и MVVM Light pattern и, таким образом, я связываю 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). Мне удалось заставить его работать с прокси (взято из 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>

Моя проблема сейчас в том, что я не знаю, как правильно получить SelectedItem (Requests_Functions.Name) в ViewModel, потому что это связанная таблица, а не полученная напрямую из ListCollectionView-Entity. Кто-нибудь знает способ, как получить SelectedItem? Я пытался с RowEditEnding EventTrigger, но всегда сталкивался с проблемой, что SelectedItem не является той же сущностью, что и ListCollectionView-Entity.

Спасибо!

1 Ответ

0 голосов
/ 10 мая 2019

Пробовали ли вы с IValueConverter, который преобразует тип объектов в списке комбинированного списка и соответствующее свойство объектов в сетке данных - добавьте его в привязку SelectedItem ComboBox?

Привязка должна быть только:

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

Просто создайте проект WPF по умолчанию в Visual Studio и вставьте его в MainWindow файлы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...