powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / ComboBox в DataGrid
8 сообщений из 8, страница 1 из 1
ComboBox в DataGrid
    #39748522
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Попробовал создать колонку в DataGrid с ComboBox... не тут-то было.
Вроде всё просто...., но никак! Чё-то упускаю, а что не доходит.
ComboBox список выводит, но не меняется привязанный элемент и не дополняется коллекция DataGrid.
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock Text="{Binding SelectedItem, ElementName=dataGrid}"/>
        <DataGrid x:Name="dataGrid" ItemsSource="{Binding Path=ListPropDG}" Grid.Row="1" ColumnWidth="*">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding PropInt}" IsReadOnly="True"/>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding PropString}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                    <DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding Path=ListProp, ElementName=window}" 
                                      SelectedItem="{Binding Path, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  
                                      DisplayMemberPath="PropString"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellEditingTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
    public partial class Example : Window
    {
        public Example()
        {
            InitializeComponent();
            DataContext = this;
        }

        /// <summary>Коллекция ComboBox</summary>
        public ObservableCollection <ExampClass> ListProp { get; set; } = new ObservableCollection<ExampClass>()
                 {
                     new ExampClass("Один",1),
                     new ExampClass("Два",2),
                     new ExampClass("Три",3),
                     new ExampClass("Четыре",4),
                     new ExampClass("Пять",5)
                 };

        /// <summary>Коллекция DataGrid</summary>
        public ObservableCollection<ExampClass> ListPropDG { get; set; } = new ObservableCollection<ExampClass>()
                 {
                     new ExampClass("Три",3),
                     new ExampClass("Пять",5)
                 };

        /// <summary>Класс для примера с двумя свойствами</summary>
        public class ExampClass : OnPropertyChangedClass
        {
            private string _propString;
            private int _propInt;

            public string PropString { get => _propString; set { _propString = value; OnPropertyChanged(); } }
            public int PropInt { get => _propInt; set { _propInt = value; OnPropertyChanged(); } }
            public ExampClass() { }
            public ExampClass(string PropString, int PropInt) { this.PropString = PropString; this.PropInt = PropInt; }

            public override string ToString() => $"Int = {PropInt}, String = {PropString}";
        }
    }


И второй вопрос. Я правильно понял, что использовать колонку DataGridComboBoxColumn можно только со статическим списком?
...
Рейтинг: 0 / 0
ComboBox в DataGrid
    #39748551
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Eld HaspComboBox список выводит, но не меняется привязанный элемент и не дополняется коллекция DataGrid
Потому что здесь вообще непонятно что творится.
Вот это
Eld Hasp
Код: sql
1.
SelectedItem="{Binding Path, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  



- что? Вы биндите SelectedItem комбобокса на свойство типа, соответствующего типу генерик-параметра ItemsSource самого DataGrid - т.е. на свойство типа ExampClass. Но у класса ExampClass нет свойства Path, это во-первых. Во-вторых, свойство типа генерик-параметра исходной коллекции (ItemsSource для DataGrid), которое вы собираетесь менять, должно быть того же типа, что и SelectedItem комбобокса (а здесь явно чувствуется попытка прикрутить SelectedItem c типом ExampClass к свойству с типом int). В противном случае для биндинга нужно задавать конвертер - в данном случае конвертер между ExampClass и int.
Eld HaspИ второй вопрос. Я правильно понял, что использовать колонку DataGridComboBoxColumn можно только со статическим списком?
Что подразумевается под "статическим списком"?
...
Рейтинг: 0 / 0
ComboBox в DataGrid
    #39748567
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сон Веры Павловны- что? Вы биндите SelectedItem комбобокса на свойство типа, соответствующего типу генерик-параметра ItemsSource самого DataGrid - т.е. на свойство типа ExampClass. Но у класса ExampClass нет свойства Path, это во-первых. Делал без Path, но выходила ошибка с указанием поставить Path.... Ну, и поставил, но работать всё равно не стало.
Сон Веры ПавловныВо-вторых, свойство типа генерик-параметра исходной коллекции (ItemsSource для DataGrid), которое вы собираетесь менять, должно быть того же типа, что и SelectedItem комбобокса (а здесь явно чувствуется попытка прикрутить SelectedItem c типом ExampClass к свойству с типом int). В противном случае для биндинга нужно задавать конвертер - в данном случае конвертер между ExampClass и int.Может я не правильно понимаю - поправьте.
В биндинг передаётся элемент коллекции ItemsSource DataGrid. В данном случае тип этого элемента ExampClass. В режиме отображения TextBlock я привязал к свойству PropString этого класса. В режиме редактирования идея была в том, чтобы ComboBox заменял сам элемент элементом из своего списка. Не одно из свойств, а весь элемент. Свойство PropInt элемента отображается в соседней колонке. Эта колонка недоступна для редактирования.
Я понимаю, что что-то неправильно здесь делаю. Но конвертер здесь для чего? По замыслу ComboBox.SelectedItem и элемент DataGrid.ItemsSource одного типа.
Сон Веры ПавловныEld HaspИ второй вопрос. Я правильно понял, что использовать колонку DataGridComboBoxColumn можно только со статическим списком?
Что подразумевается под "статическим списком"?Статический, то есть неизменяемый. В инете примеры которые видел все с привязкой ItemsSource к StaticResource или прямой инициализацией списка в XAML. Попробовал привязать к списочному свойству - ничего не показывает.
...
Рейтинг: 0 / 0
ComboBox в DataGrid
    #39748568
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Чуть более развёрнутый пример.
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock Text="{Binding SelectedItem, ElementName=dataGrid}"/>
        <DataGrid x:Name="dataGrid" ItemsSource="{Binding Path=ListPropDG}" Grid.Row="1" ColumnWidth="*">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding PropValue}"/>
                <DataGridTextColumn Binding="{Binding PropCombo.PropInt}" IsReadOnly="True"/>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding PropString}" FontSize="{Binding PropCombo.PropString}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                    <DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding ListProp, ElementName=window}" 
                                      SelectedItem="{Binding PropCombo}"  
                                      DisplayMemberPath="PropString"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellEditingTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
    public partial class Example : Window
    {
        public Example()
        {
            InitializeComponent();
            DataContext = this;
        }

        /// <summary>Коллекция ComboBox</summary>
        public ObservableCollection <ExampClass> ListProp { get; set; } = new ObservableCollection<ExampClass>()
                 {
                     new ExampClass("Один",1),
                     new ExampClass("Два",2),
                     new ExampClass("Три",3),
                     new ExampClass("Четыре",4),
                     new ExampClass("Пять",5)
                 };

        /// <summary>Коллекция DataGrid</summary>
        public ObservableCollection<ExampTwoClass> ListPropDG { get; set; } = new ObservableCollection<ExampTwoClass>()
                 {
                    new ExampTwoClass("One", new ExampClass("Три",3)),
                    new ExampTwoClass("Two", new ExampClass("Пять",5))
                 };

        /// <summary>Класс для примера с двумя свойствами</summary>
        public class ExampTwoClass : OnPropertyChangedClass
        {
            private string _propValue;
            private ExampClass _propCombo;

            public string PropValue { get => _propValue; set { _propValue = value; OnPropertyChanged(); } }
            public ExampClass PropCombo { get => _propCombo; set { _propCombo = value; OnPropertyChanged(); } }
            public ExampTwoClass() { }
            public ExampTwoClass(string PropString, ExampClass PropCombo) { this.PropValue = PropString; this.PropCombo = PropCombo; }

            public override string ToString() => $"String = {PropValue}, PropCombo = {{{PropCombo.ToString()}}}";
        }

        /// <summary>Класс для примера с двумя свойствами</summary>
        public class ExampClass : OnPropertyChangedClass
        {
            private string _propString;
            private int _propInt;

            public string PropString { get => _propString; set { _propString = value; OnPropertyChanged(); } }
            public int PropInt { get => _propInt; set { _propInt = value; OnPropertyChanged(); } }
            public ExampClass() { }
            public ExampClass(string PropString, int PropInt) { this.PropString = PropString; this.PropInt = PropInt; }

            public override string ToString() => $"Int = {PropInt}, String = {PropString}";
        }
    }
...
Рейтинг: 0 / 0
ComboBox в DataGrid
    #39748569
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ох! Пропустил одну строчку - не исправил.
Код: xml
1.
2.
3.
4.
5.
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding PropCombo.PropString}" FontSize="{Binding PropCombo.PropString}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
...
Рейтинг: 0 / 0
ComboBox в DataGrid
    #39748570
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Во втором примере, работает как задумывалось. А первый, вроде тоже самое - не работает. Как-то не так привязки указываю. На мой взгляд, оба примера одно и тоже.
...
Рейтинг: 0 / 0
ComboBox в DataGrid
    #39748572
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если из первого примера убрать Path, то при попытке редактирования строки выходит такая ошибка (на скриншоте)
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
        <DataGrid x:Name="dataGrid" ItemsSource="{Binding Path=ListPropDG}" Grid.Row="1" ColumnWidth="*">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding PropInt}" IsReadOnly="True"/>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding PropString}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                    <DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding ListProp, ElementName=window}" 
                                      SelectedItem="{Binding}"  
                                      DisplayMemberPath="PropString"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellEditingTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
...
Рейтинг: 0 / 0
ComboBox в DataGrid
    #39748599
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Eld Hasp,

Вот вполне работающий пример - разбирайтесь, там всё вполне очевидно.
Код
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
public partial class MainWindow
{
  public MainWindow()
  {
    InitializeComponent();
    DataContext = this;
  }

  public ObservableCollection<DiaryRecord> Diary { get; } = new ObservableCollection<DiaryRecord>{ new DiaryRecord() };
  public ObservableCollection<DiaryRecord2> Diary2 { get; } = new ObservableCollection<DiaryRecord2> { new DiaryRecord2() };
}

public class DayOfWeekX
{
  public DayOfWeekX():this(0) { }

  public DayOfWeekX(int dayOfWeek)
  {
    N = dayOfWeek;
    Name = DayName(dayOfWeek);
  }

  public int N { get; }
  public string Name { get; }

  public override bool Equals(object obj) => obj is DayOfWeekX dx && dx.N==N;
  public override int GetHashCode() => N.GetHashCode();
  public override string ToString() => $"[{GetType().Name}] {Name} ({N})";

  static readonly Dictionary<int, string> days = new Dictionary<int, string>
  {
    { 0, "Понедельник" },
    { 1, "Вторник" },
    { 2, "Среда" },
    { 3, "Четверг" },
    { 4, "Пятница" },
    { 5, "Суббота" },
    { 6, "Воскресенье" }
  };

  public static IReadOnlyCollection<DayOfWeekX> DaysOfWeek { get; }
  public static string DayName(int dayOfWeek) => days[dayOfWeek];

  static DayOfWeekX()
    => DaysOfWeek = days.Select(kvp => new DayOfWeekX(kvp.Key))
      .OrderBy(d => d.N).ToList();
}

public class DiaryRecordBase : INotifyPropertyChanged
{
  protected DiaryRecordBase() => Description = string.Empty;

  string _description;
  public string Description
  {
    get => _description;
    set
    {
      _description = value;
      OnPropertyChanged();
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;

  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public class DiaryRecord: DiaryRecordBase
{
  public DiaryRecord() => Day = new DayOfWeekX();

  DayOfWeekX _day;
  public DayOfWeekX Day
  {
    get => _day;
    set
    {
      _day = value;
      OnPropertyChanged();
    }
  }
}

public class DiaryRecord2 : DiaryRecordBase
{
  public IReadOnlyCollection<DayOfWeekX> Days => 
    Day%2==0
      ? DayOfWeekX.DaysOfWeek
      : DayOfWeekX.DaysOfWeek.OrderByDescending(d=>d.N).ToList();

  int _day;
  public int Day
  {
    get => _day;
    set
    {
      _day = value;
      OnPropertyChanged();
      OnPropertyChanged(nameof(DayName));
      Application.Current.Dispatcher.
        BeginInvoke(DispatcherPriority.ContextIdle,
        (Action)(()=> OnPropertyChanged(nameof(Days))));
    }
  }

  public string DayName => DayOfWeekX.DayName(Day);
}

public class DayOfWeekConverter : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    if (!(value is int n))
      throw new ArgumentException();
    var dx = DayOfWeekX.DaysOfWeek.FirstOrDefault(dw => dw.N == n);
    return dx ?? throw new ArgumentException();
  }

  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    => value is DayOfWeekX dx ? (object)dx.N : null;
}


Разметка
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
<Grid>
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>
  <DataGrid
    CanUserAddRows="True"
    ItemsSource="{Binding Diary}"
    AutoGenerateColumns="False">
    <DataGrid.Columns>
      <DataGridTemplateColumn Header="День недели">
        <DataGridTemplateColumn.CellTemplate>
          <DataTemplate>
            <TextBlock Text="{Binding Day.Name}"/>
          </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
        <DataGridTemplateColumn.CellEditingTemplate>
          <DataTemplate>
            <ComboBox
              ItemsSource="{Binding Source={x:Static local:DayOfWeekX.DaysOfWeek}}" 
              SelectedItem="{Binding Day, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  
              DisplayMemberPath="Name"/>
          </DataTemplate>
        </DataGridTemplateColumn.CellEditingTemplate>
      </DataGridTemplateColumn>
      <DataGridTextColumn
        Header="Описание"
        Width="*"
        Binding="{Binding Description, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    </DataGrid.Columns>
  </DataGrid>
  <DataGrid
    Grid.Row="1"
    Margin="0,10,0,0"
    CanUserAddRows="True"
    ItemsSource="{Binding Diary2}"
    AutoGenerateColumns="False">
    <DataGrid.Columns>
      <DataGridTemplateColumn Header="День недели">
        <DataGridTemplateColumn.CellTemplate>
          <DataTemplate>
            <TextBlock Text="{Binding DayName}"/>
          </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
        <DataGridTemplateColumn.CellEditingTemplate>
          <DataTemplate>
            <DataTemplate.Resources>
              <local:DayOfWeekConverter x:Key="DayOfWeekConverter" />
            </DataTemplate.Resources>
            <ComboBox
              ItemsSource="{Binding Days}" 
              SelectedItem="{Binding Day, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource DayOfWeekConverter}}"
              DisplayMemberPath="Name"/>
          </DataTemplate>
        </DataGridTemplateColumn.CellEditingTemplate>
      </DataGridTemplateColumn>
      <DataGridTextColumn
        Header="Описание"
        Width="*"
        Binding="{Binding Description, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    </DataGrid.Columns>
  </DataGrid>
</Grid>


В верхнем датагриде SelectedItem комбобокса связан со свойством такого же типа из элемента ItemsSource датагрида, ItemsSource комбобокса статический. В нижнем датагриде SelectedItem комбобокса связан со свойством другого типа из элемента ItemsSource датагрида, и поэтому используется конвертер, ItemsSource комбобокса динамический (привязан к свойству элемента из ItemsSource датагрида). Визуально это выражается в том, что если выбрать нечетный день недели, список в комбобоксе будет отсортирован по возрастанию номера дня недели, если выбрать нечетный - по убыванию.
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / ComboBox в DataGrid
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]