1

Есть DataGrid с 2 столбцами (один текстовый, другой ComboBox) к которому привязан ObservableCollection. По нажатию кнопки в DataGrid должна появиться новая строка.

xaml:

<DataGrid Name="rDG" ItemsSource="{Binding Provlist}" Height="208" Width="355" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Имя" Binding="{Binding ima}"/>
        <DataGridComboBoxColumn x:Name="rCC"  Header="Тип" SelectedValueBinding="{Binding idRegtype}" SelectedValuePath="idRegtype" DisplayMemberPath="Regtype_name">
            <DataGridComboBoxColumn.ElementStyle>
                <Style TargetType="{x:Type ComboBox}">
                    <Setter Property="ItemsSource" Value="{Binding Path=SpisokRegtypes, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
                </Style>
            </DataGridComboBoxColumn.ElementStyle>
            <DataGridComboBoxColumn.EditingElementStyle>
                <Style TargetType="{x:Type ComboBox}">
                    <Setter Property="ItemsSource" Value="{Binding Path=SpisokRegtypes, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
                </Style>
            </DataGridComboBoxColumn.EditingElementStyle>
        </DataGridComboBoxColumn>
    </DataGrid.Columns>
</DataGrid>
<Button Content="Button" Click="Button_Click" HorizontalAlignment="Left" Margin="661,214,0,0" VerticalAlignment="Top" Width="75" />

Собственно создание коллекций spisokRegtypes - для заполнения комбобокса, и Provlist - явл. строкой в dataGrid, держащей в себе комбобокс:

private ObservableCollection<Regtype> _spisokRegtypes;
private ObservableCollection<RList> _Provlist;

public class RList
{
    public string ima { get; set; }
    public int idRegtype { get; set; }
}

public class Regtype
{
    public int idRegtype { get; set; }
    public string Regtype_name { get; set; }
}

public ObservableCollection<Regtype> SpisokRegtypes
{
    get
    {
        return _spisokRegtypes;
    }
    set
    {
        _spisokRegtypes = value;
        OnPropertyChanged();
    }
}
public ObservableCollection<RList> Provlist
{
    get
    {
        return _Provlist;
    }
    set
    {
        _Provlist = value;
        OnPropertyChanged();
    }
}

Метод, отвечающий за INotifyPropertyChanged:

public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName]string propertyName = "")
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

Добавление нового элемента по нажатию кнопки:

public void Button_Click(object sender, RoutedEventArgs e)
{
    SpisokRegtypes = new ObservableCollection<Regtype>();
    SpisokRegtypes.Add(new Regtype() { idRegtype = 0, Regtype_name = "Столица"});
    SpisokRegtypes.Add(new Regtype() { idRegtype = 1, Regtype_name = "Регион" });

    Provlist = new ObservableCollection<RList>();
    Provlist.Add(new RList() { ima = "название", idRegtype = 1 });

    rDG.ItemsSource = null;
    rDG.ItemsSource = Provlist;
}

По нажатию кнопки успешно создаётся первая строка, но при повторном нажатии - ничего не меняется, как была одна строка так и осталась. Если вручную добавить строки, а потом нажать на кнопку, то ранее добавленные строки исчезнут и останется лишь строка добавленная кнопкой. Пытался через ItemSource что-то сделать, но в итоге безрезультатно.

insolor
  • 49,104
Domed
  • 39
  • как была одна строка так и осталась - ну наверно потому, что вы все время создаете новый объект коллекции (Provlist = new ObservableCollection<RList>();)? – EvgeniyZ Mar 08 '20 at 18:02
  • 1
    У вас в методе логическая ошибка. При каждом нажатии вы заново создаете коллекции, а надо бы проверять, если коллекция уже существует, то просто добавляем новую строку иначе делаем все то, что у вас уже написано в методе. – Bulson Mar 08 '20 at 18:04
  • @EvgeniyZ и Bulson Странно, я был уверен что я создаю таким образом экземпляр с помощью которого и можно всё это делать... А как тогда можно сделать проверку на наличие уже существующей коллекции? – Domed Mar 08 '20 at 18:11
  • 1
    new - новый, то есть это будто у вас 2 листа бумаги, на одном вы написали "привет мир", будут ли изменения на 2-м? Как сделать проверку: Ну самое простое if (Provlist == null) Provlist = new ObservableCollection<RList>();. Если эта коллекция не подразумевает быть NULL и вам она нужна постоянно инициализированная, то как вариант сделать просто public ObservableCollection<RList> Provlist { get; } = new..., дальше уже просто добавлять/удалять в нее объекты. Также зачем вы делаете rDG.ItemsSource = Provlist;? Вы ведь используете привязки, так задайте один раз DataContext и все. – EvgeniyZ Mar 08 '20 at 18:21
  • @EvgeniyZ Благодарю за разжёвывание новичку. Сделав проверку всё стало нормально работать. – Domed Mar 08 '20 at 18:46

1 Answers1

1
SpisokRegtypes = new ObservableCollection<Regtype>();

Вот это надо убрать и использовать только тогда, когда вам надо создать новую коллекцию.

Вместо этого создание новой коллекции в случае если она еще не существует, можно автоматизировать следующим образом:

public ObservableCollection<Regtype> SpisokRegtypes
{
    get
    {
        // то же самое что if (_spisokRegtypes == null) return (_spisokRegtypes = new ObservableCollection<Regtype>());
        // else return _spisokRegtypes;
        return _spisokRegtypes ?? (_spisokRegtypes = new ObservableCollection<Regtype>());
    }
    set
    {
        _spisokRegtypes = value;
        OnPropertyChanged();
    }
}

В этом случае коллекция будет создана впервые тогда, когда кто-либо к ней обратится (вызовет get), а это обычно происходит когда выполняется InitializeComponent() у окна, вызов сделает DataGrid. То есть, если вы выполняете код после это вызова, то бояться, что коллекция на момент выполнения кода не инициализирована, не придется.

aepot
  • 49,560