none
WPF - Datagrid und ComboBox RRS feed

  • Frage

  • Hallo, ich habe eine WPF-Anwendung und versuche in einem DataGrid (Extended WPF Toolkit) eine ComboBox an mein ViewModel zu binden. 

    public class MainWindowViewModel
        {
     
            public ObservableCollection<Country> Countries { get; set; }
            public ObservableCollection<string> Continents { get; set; }
    
    
            public MainWindowViewModel(IReader reader)
            {
                _reader = reader;
                Countries = new ObservableCollection<Country>(_reader.Get());
                Continents = new ObservableCollection<string>(Countries.Select(c => c.Continent).Distinct());
            }
        }

    Die Klasse Country sieht so aus:

      public class Country
        {
            public string Name { get; set; }
            public string Continent { get; set; }
        }

    Mein XAML seht so aus:

    xcdg:DataGridControl x:Name="_dataGrid" 
                                MaxHeight="400"
                                ItemsSource="{Binding Countries}" >
         
                <xcdg:DataGridControl.View>
                    <xcdg:TableflowView xcdg:GroupLevelIndicatorPane.ShowIndicators="False"/>
                </xcdg:DataGridControl.View>
    
                <xcdg:DataGridControl.Columns>
                    <xcdg:Column FieldName="Name"
                                IsMainColumn="True">
                    </xcdg:Column>
                    <xcdg:Column FieldName="Continent">
                        <xcdg:Column.CellContentTemplate>
                            <DataTemplate>
                                <ComboBox 
                                  ....
                                   />
                            </DataTemplate>
                        </xcdg:Column.CellContentTemplate>
                    </xcdg:Column>
                </xcdg:DataGridControl.Columns>
            </xcdg:DataGridControl>

    Die CombBox soll an das jeweilige Country.Continent gebunden werden, so dass im Grid das korrekte Kontintent des jeweiligen Staates angezigt wird. Mit Hilfe der 

    ObservableCollection<string> Continents { get; set; }

    sollen die möglichen Werte in die ComboBox geladen werden. 

    We kann ich erreichen, dass die ComBox an das jeweilige Country-Objekt gebunden wird?

    Danke für die Hilfe!

    Adi

    Sonntag, 18. November 2018 12:22

Antworten

  • Hi Adi,
    wie das von Dir genutzte DataGrid funktioniert, kann ich leider nicht sagen. Als Anregung nachfolgend ein Beispiel (MVVM Entwurfsmuster) mit dem DataGrid aus dem Framework. In der Demo wird genau das gemacht, was Du angefragt hast.

    XAML:

    <Window x:Class="WpfApp1.Window78"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            mc:Ignorable="d"
            Title="Window78" Height="450" Width="800">
      <Window.Resources>
        <local:Window78VM x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <DataGrid ItemsSource="{Binding Countries}" AutoGenerateColumns="False">
          <DataGrid.Columns>
            <DataGridTextColumn Header="Country" Binding="{Binding Name}"/>
            <DataGridComboBoxColumn Header="Continent" Width="100"
                                    ItemsSource="{Binding Path=Continents, Source={StaticResource vm}}"
                                    DisplayMemberPath="Continent"
                                    SelectedValueBinding="{Binding FKContinent}"
                                    SelectedValuePath="ID"/>
          </DataGrid.Columns>
        </DataGrid>
      </Grid>
    </Window>

    Dazu der ViewModel und die Datenklassen:

    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Data;
    
    namespace WpfApp1
    {
      public class Window78VM
      {
        public Window78VM()
        {
          for (int i = 1; i < 10; i++)
            _countries.Add(new Window78Country()
            {
              Name = $"Land {i}",
              FKContinent = i
            });
          cvs1.Source = _countries;
          for (int i = 1; i < 10; i++)
            _continent.Add(new Window78Continent()
            {
              ID=i,
              Continent = $"Kontinent {i}"
            });
          cvs2.Source = _continent;
        }
        private ObservableCollection<Window78Country> _countries = new ObservableCollection<Window78Country>();
        private CollectionViewSource cvs1 = new CollectionViewSource();
        public ICollectionView Countries { get { return cvs1.View; } }
    
        private ObservableCollection<Window78Continent> _continent = new ObservableCollection<Window78Continent>();
        private CollectionViewSource cvs2 = new CollectionViewSource();
        public ICollectionView Continents { get { return cvs2.View; } }
      }
      public class Window78Country
      {
        public string Name { get; set; }
        public int FKContinent { get; set; }
      }
      public class Window78Continent
      {
        public int ID { get; set; }
        public string Continent { get; set; }
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks


    Sonntag, 18. November 2018 15:30
  • Hi Adi,
    den vollständigen Code habe ich doch in meinem Post. Kopiere ihn einfach in ein neues Projekt und passe ggf. das an, was bei die anders lautet (z.B. Namensraum, Window-Name).

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    Sonntag, 18. November 2018 16:15

Alle Antworten

  • Hi Adi,
    wie das von Dir genutzte DataGrid funktioniert, kann ich leider nicht sagen. Als Anregung nachfolgend ein Beispiel (MVVM Entwurfsmuster) mit dem DataGrid aus dem Framework. In der Demo wird genau das gemacht, was Du angefragt hast.

    XAML:

    <Window x:Class="WpfApp1.Window78"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            mc:Ignorable="d"
            Title="Window78" Height="450" Width="800">
      <Window.Resources>
        <local:Window78VM x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <DataGrid ItemsSource="{Binding Countries}" AutoGenerateColumns="False">
          <DataGrid.Columns>
            <DataGridTextColumn Header="Country" Binding="{Binding Name}"/>
            <DataGridComboBoxColumn Header="Continent" Width="100"
                                    ItemsSource="{Binding Path=Continents, Source={StaticResource vm}}"
                                    DisplayMemberPath="Continent"
                                    SelectedValueBinding="{Binding FKContinent}"
                                    SelectedValuePath="ID"/>
          </DataGrid.Columns>
        </DataGrid>
      </Grid>
    </Window>

    Dazu der ViewModel und die Datenklassen:

    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Data;
    
    namespace WpfApp1
    {
      public class Window78VM
      {
        public Window78VM()
        {
          for (int i = 1; i < 10; i++)
            _countries.Add(new Window78Country()
            {
              Name = $"Land {i}",
              FKContinent = i
            });
          cvs1.Source = _countries;
          for (int i = 1; i < 10; i++)
            _continent.Add(new Window78Continent()
            {
              ID=i,
              Continent = $"Kontinent {i}"
            });
          cvs2.Source = _continent;
        }
        private ObservableCollection<Window78Country> _countries = new ObservableCollection<Window78Country>();
        private CollectionViewSource cvs1 = new CollectionViewSource();
        public ICollectionView Countries { get { return cvs1.View; } }
    
        private ObservableCollection<Window78Continent> _continent = new ObservableCollection<Window78Continent>();
        private CollectionViewSource cvs2 = new CollectionViewSource();
        public ICollectionView Continents { get { return cvs2.View; } }
      }
      public class Window78Country
      {
        public string Name { get; set; }
        public int FKContinent { get; set; }
      }
      public class Window78Continent
      {
        public int ID { get; set; }
        public string Continent { get; set; }
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks


    Sonntag, 18. November 2018 15:30
  • Hallo, wo finde ich das Demo!

    Danken dir!

    Sonntag, 18. November 2018 15:44
  • Hi Adi,
    den vollständigen Code habe ich doch in meinem Post. Kopiere ihn einfach in ein neues Projekt und passe ggf. das an, was bei die anders lautet (z.B. Namensraum, Window-Name).

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    Sonntag, 18. November 2018 16:15