Почему collection1 имеет те же значения, что и collection2? - PullRequest
0 голосов
/ 29 июня 2018

Что я хочу

Итак, я хочу проверить 2 ObservableCollections, равны ли они друг другу. Если это так, верните Nothing Changed (collection1 и collection2 одинаковы). В противном случае верните Something Changed.

Проблема

Проблема в том, что обе коллекции содержат одинаковые значения, даже когда я изменяю элементы из коллекции 2.

Я опубликовал некоторый код и gif результата отладки, чтобы показать вам, что я получаю. Я не понимаю, почему обе коллекции одинаковые после нажатия кнопки «Сохранить».

код

ViewModel

В моей ViewModel у меня есть: 1 ObservableCollection называется RightsCollection. Это должно содержать права на мой XAML, которые я могу изменить с помощью ToggleButton.

1 Employee класс, где расположен ObservableCollection<Groups>, а внутри Groups.Col есть ObservableCollection<Rights>, который содержит права группы по умолчанию, которые были загружены из базы данных, которые не могут быть изменены.

Примечание: мои get set всегда одинаковы. У них просто есть другие имена, и DataTypes считают его тип данных поля.

private Employee _singleEmployee = new Employee();
public Employee SingleEmployee
{
    get => _singleEmployee;
    set
    {
        if (_singleEmployee == value) return;
        _singleEmployee = value;
        OnPropertyChanged("SingleEmployee");
    }
}

private ObservableCollection<Groups> _groupsCollection = new ObservableCollection<Groups>();
// public get set GroupsCollection (same like first).

private ObservableCollection<Rights> _rightsCollection = new ObservableCollection<Rights>();
// public get set RightsCollection (same like first).

Класс сотрудника

public class Employee : INotifyPropertyChanged
{
    private int _employeeId;
    private string _firstName;
    private Groups _group = new Group();

    // public get set EmployeeId (Same like first).
    // public get set Group (same like first).
}

Класс прав

private int _rightId;
private string _rightName;
private bool _hasRight;

// Again get set is same

Группы Класс

private int _groupId;
private string _groupName;
private ObservableCollection<Rights> _rights;

// Again, same Get/Set like always

XAML

В моем XAML у меня есть: ComboBox. ComboBox.ItemsSource привязать к GroupsCollection. ComboBox.SelectedValue привязка к SingleEmployee.Group.

Таким образом, при изменении ComboBox будет установлена ​​группа одного сотрудника.

Этот ComboBox также получил SelectionChanged Событие, где я установил RightsCollection равным SingleEmployee.Group.Rights. Так что теперь оба содержат одинаковые элементы / значения.

Он также содержит ItemsControl, где я могу установить права самостоятельно (и где права будут загружены, когда ComboBox.SelectionChanged (что работает).

<ComboBox x:Name="GroupComboBox" ItemsSource="{Binding GroupsCollection}" SelectedValue="{Binding SingleEmployee.Group}" DisplayMemberPath="GroupName" SelectionChanged="GroupComboBox_SelectionChanged">

ItemsControl

<ItemsControl ItemsSource="{Binding RightsCollection}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <DockPanel>
                    <ToggleButton DockPanel.Dock="Right" Margin="10" IsChecked="{Binding HasRight}"/>
                    <TextBlock FontSize="15" FontWeight="Bold" Text="{Binding RightName}" DockPanel.Dock="Left" Margin="10" />
                </DockPanel>
                <TextBlock Text="{Binding RightsDesc}" Margin="30 0 0 10" TextWrapping="Wrap"/>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Событие SelectionChanged в коде позади

Debug.WriteLine("############ SelectionChanged Event ############");
Debug.WriteLine("# Before Change ##");
Debug.WriteLine($"SingleEmployee.Group.Rights.Count: {_viewModel.SingleEmployee.Group.Rights.Count} | RightsCollection.Count: {_viewModel.RightsCollection.Count}");
for (int i = 0; i < _viewModel.SingleEmployee.Group.Rights.Count; i++)
{
    Debug.WriteLine($"Name: {_viewModel.SingleEmployee.Group.Rights[i].RightName}, HasRight: {_viewModel.SingleEmployee.Group.Rights[i].HasRight} || Name: {_viewModel.RightsCollection[i].RightName}, HasRight: {_viewModel.RightsCollection[i].HasRight}");
}

_viewModel.RightsCollection = _viewModel.SingleEmployee.Group.Rights;

Debug.WriteLine("# After Change #");
Debug.WriteLine($"SingleEmployee.Group.Rights.Count: {_viewModel.SingleEmployee.Group.Rights.Count} | RightsCollection.Count: {_viewModel.RightsCollection.Count}");
for (int i = 0; i < _viewModel.SingleEmployee.Group.Rights.Count; i++)
{
    Debug.WriteLine$"Name: {_viewModel.SingleEmployee.Group.Rights[i].RightName}, HasRight: {_viewModel.SingleEmployee.Group.Rights[i].HasRight} || Name: {_viewModel.RightsCollection[i].RightName}, HasRight: {_viewModel.RightsCollection[i].HasRight}");
}

Debug.WriteLine("########## SelectionChanged Event END ##########");
Debug.WriteLine("################################################");

Установить ViewModel в Code-Behind

private readonly EmployeeViewModel _viewModel;

// constructor...
{
_viewModel = (EmployeeViewModel) DataContext;
}

Метод команды кнопки сохранения

Debug.WriteLine("############## After Button Click ##############");
for (int i = 0; i < RightsCollection.Count; i++)
{
    Debug.WriteLine($"Name: {SingleEmployee.Group.Rights[i].RightName}, HasRight: {SingleEmployee.Group.Rights[i].HasRight} || Name: {RightsCollection[i].RightName}, HasRight: {RightsCollection[i].HasRight}");
}
Debug.WriteLine("################################################");

bool equal = RightsCollection.Count == SingleEmployee.Group.Rights.Count && RightsCollection.All(x => SSingleEmployee.Group.Rights.Contains(x));

Debug.WriteLine(equal ? "Nothing Changed" : "Something changed");

Что я пробовал

Событие SelectionChanged

// No Success
var collection = new ObservableCollection<Rights>(_viewModel.SingleEmployee.Group.Rights);
_viewModel.RightsCollection = collection;

.

// No Success
foreach(var item in _viewModel.SingleEmployee.Group.Rights)
    _viewModel.RightsCollection.Add(item);

Результат отладки

SelectionChangedResult SelectionChangedResult (GIF) |

SelectionChangedResult SelectionChangedResult (Picture)

после нажатия кнопки After Button Click (GIF)

после нажатия кнопки After Button Click (Picture)

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

Я исправил эту проблему в моем SelectionChanged Event удалении этой строки:

_viewModel.RightsCollection = _viewModel.SingleEmployee.Group.Rights;

и заменил его следующим:

for (int i = 0; i < _viewModel.SingleEmployee.Group.Rights.Count; i++)
{
    if (_viewModel.SingleEmployee.Group.Rights[i].HasRight != _viewModel.RightsCollection[i].HasRight)
    {
        _viewModel.RightsCollection[i].HasRight = _viewModel.SingleEmployee.Group.Rights[i].HasRight;
    }
}

Поскольку обе коллекции почти одинаковы, у них всегда будет одинаковое количество предметов, поэтому я могу использовать for -петл. Если значение не совпадает, оно изменится.

Таким образом, я не создаю отражение (наверное), поэтому оно работает.

Теперь единственное, что

bool equal = RightsCollection.Count == SingleEmployee.Group.Rights.Count && RightsCollection.All(x => SingleEmployee.Group.Rights.Contains(x)); 

не работает, но здесь я также буду использовать цикл for, который проверяет, содержит ли элемент одинаковое значение, если нет, то "Something changed".

0 голосов
/ 29 июня 2018
_viewModel.RightsCollection = _viewModel.SingleEmployee.Group.Rights;

левая коллекция имеет ту же ссылку, что и правая коллекция. Таким образом, если вы измените одну коллекцию, она будет отражена в другой коллекции.

ObservableCollection<Whatever> _viewModel.RightsCollection = new ObservableCollection<Whatever>();

foreach(var item in _viewModel.SingleEmployee.Group.Rights)
    _viewModel.RightsCollection.Add(item);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...