Связывание wpf ComboBox в виде списка - PullRequest
0 голосов
/ 06 марта 2020

У меня проблема с привязкой ComboBox в ListView

В ComboBox мне нужно связать объект User из объекта ListDetails. Если я изменяю ComboBox, он работает, если я открываю окно, привязка не работает. ComboBoxItem - это полный список всех существующих пользователей из полного кода ДБ.

<GridViewColumn x:Name="colUser" Header="User.Name in ComboBox">
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <ComboBox Width="300" SelectionChanged="ComboBox_SelectionChanged"
                            ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:MainWindow}}, Path=AlleUser}"
                            SelectedValue="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListViewItem}}, Path=DataContext.User}" 
                            SelectedValuePath="Key" DisplayMemberPath="Value"/>
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>

, который вы можете увидеть в https://github.com/fialo4ka/ListBinding/tree/master Например, я изменяю загрузку БД на некоторые тестовые данные

Ответы [ 3 ]

0 голосов
/ 06 марта 2020

Во-первых, вы никогда не должны смешивать привязку данных и задавать значения непосредственно в code-behind. Это делает отладку и понимание кода намного труднее для всех, включая вас самих. Выбери один. Я настоятельно рекомендую привязку данных. Я изменил код, чтобы использовать только привязку данных.

У меня работает следующий код. Значения отображаются в ComboBox.
Если это все еще не работает должным образом, вам необходимо уточнить точно , что вы делаете, что вы ожидаете и что на самом деле происходит.

Также обычно вы не устанавливаете свойство ItemsControl.SelctedValue. Это свойство содержит результат ItemsControl.SelectedValuePath после выбора элемента. В вашем случае, когда выбранное значение должно быть значением User.Name, вам необходимо установить путь на SelectedValuePath="Key.Name", поскольку Key ссылается на элемент User KeyValuePair, а затем Name the User.Name собственность. Вы должны связать SelectedValue со свойством в классе MainWindow, чтобы получить к нему доступ или к другому элементу управления, например, TextBlock.Text.

При чтении новых данных из базы данных вы сначала очищаете коллекции а затем добавить новые предметы. Поскольку вы используете ObservableCollection, представления будут обновляться автоматически. Не устанавливайте виды напрямую.

MainWindow.xaml

<Window>
  <Grid>    
    <Grid.RowDefinitions>
      <RowDefinition />
      <RowDefinition />
      <RowDefinition />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition />
      <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <ListView Name="lvBezirke" 
              ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type main:MainWindow}}, Path=ListDetails}"
              Grid.ColumnSpan="2">
      <ListView.View>
        <GridView ColumnHeaderToolTip="zugeordnete User je Bezirk">
          <GridViewColumn x:Name="colBezirk" Header="Some Data from model" DisplayMemberBinding="{Binding Bezirk}" />
          <GridViewColumn x:Name="colUser" Header="User.Name in ComboBox">
            <GridViewColumn.CellTemplate>
              <DataTemplate>
                <ComboBox Width="300" SelectionChanged="ComboBox_SelectionChanged"
                          ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type main:MainWindow}}, Path=AlleUser}"                              
                          SelectedValuePath="Key" DisplayMemberPath="Value" />
              </DataTemplate>
            </GridViewColumn.CellTemplate>
          </GridViewColumn>
          <GridViewColumn Header="User.Loginname" DisplayMemberBinding="{Binding User.Loginname}" />
          <GridViewColumn Header="User.Name" DisplayMemberBinding="{Binding User.Name}" />
        </GridView>
      </ListView.View>
    </ListView>
    <Button Grid.Row="1" Content="click" Click="Button_Click" />
    <Button Grid.Row="1" Grid.Column="1" Content="clear" Click="Button_Click_1" />
    <ListView Name="lvBezirkeClick"
              ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type main:MainWindow}}, Path=ListDetailsClick}"
              Grid.Row="2" Grid.ColumnSpan="2" >
      <ListView.View>
        <GridView ColumnHeaderToolTip="zugeordnete User je Bezirk">
          <GridViewColumn Header="Some Data from model" DisplayMemberBinding="{Binding Bezirk}" />
          <GridViewColumn Header="User.Loginname onClick" DisplayMemberBinding="{Binding User.Loginname}" />
          <GridViewColumn Header="User.Name onClick" DisplayMemberBinding="{Binding User.Name}" />
        </GridView>
      </ListView.View>
    </ListView>
  </Grid>
</Window>

MainWindow.xaml.cs

partial class MainWindow
{
  public ObservableCollection<ListDetails> ListDetails { get; set; }
  public ObservableCollection<ListDetails> ListDetailsClick { get; set; }
  public ObservableCollection<KeyValuePair<User, string>> AlleUser { get; set; }

  public MainWindow()
  {
    InitializeComponent();  // Always the first line in constructor!

    this.ListDetailsClick = new ObservableCollection<ListDetails>();

    // Initialize ObservableCollection directly
    this.ListDetails = new ObservableCollection<ListDetails>()
    {
      new ListDetails("data 1", new User("1 user", "1")),
      new ListDetails("data 2", new User("8 user", "8")),
      new ListDetails("data 3", new User("5 user", "5")),
    };

    this.AlleUser = new ObservableCollection<KeyValuePair<User, string>>()
    {
      { new KeyValuePair<User, string>(new User("1 user", "1"), "1") },
      { new KeyValuePair<User, string>(new User("2 user", "2"), "2") },
      { new KeyValuePair<User, string>(new User("4 user", "3"), "3") },
      { new KeyValuePair<User, string>(new User("4 user", "4"), "4") },
      { new KeyValuePair<User, string>(new User("5 user", "5"), "5") },
      { new KeyValuePair<User, string>(new User("6 user", "6"), "6") },
      { new KeyValuePair<User, string>(new User("7 user", "7"), "7") },
      { new KeyValuePair<User, string>(new User("8 user", "8"), "8") },
    };
  }

  private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
  {

  }

  // Clear and copy
  private void Button_Click(object sender, RoutedEventArgs e)
  {
    this.ListDetailsClick.Clear();
    this.ListDetails.ToList().ForEach(this.ListDetailsClick.Add);
  }

  private void Button_Click_1(object sender, RoutedEventArgs e)
  {
    this.ListDetailsClick.Clear();
  }
}
0 голосов
/ 10 марта 2020

Итак ... Попробовав все эти ответы, я все еще не вижу имя пользователя в форме загрузки, поэтому я нашел решение, которое напрямую поместило имя в ComboBox. но я все еще не могу понять, почему все предыдущие решения не работают для меня :(

        private void ComboBox_Loaded(object sender, RoutedEventArgs e)
        {
            ((ComboBox)sender).Text = ((ListDetails)((ComboBox)sender).DataContext).User.Name;
        }
<DataTemplate>
    <ComboBox Width="300" SelectionChanged="ComboBox_SelectionChanged" Loaded="ComboBox_Loaded"
                    ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:MainWindow}}, Path=AlleUser}"
                    SelectedValue="{Binding User}" 
                    SelectedValuePath="Key" DisplayMemberPath="Key.Value"/>
0 голосов
/ 06 марта 2020

Необходимо связать со свойством User объекта ListDetails:

<ComboBox Width="300" ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:MainWindow}}, Path=AlleUser}"
          SelectedValue="{Binding User}" 
          SelectedValuePath="Key" DisplayMemberPath="Key.Name"/>
...