Pielroja
Pielroja

Reputation: 35

Why does collection1 has the same values like collection2?

What I want

So I want to check 2 ObservableCollections if they equals each other. If so, then return Nothing Changed (collection1 and collection2 are the same). Otherwise return Something Changed.

The Problem

The problem now is, that both collection contains the same values even when I change items from collection 2.

I posted some Code and gif of the Debug result to show you what I get. I dont understand, why both Collections are the same after clicking the Save Button.

Code

ViewModel

In my ViewModel I have: 1 ObservableCollection called RightsCollection. This should contain the rights on my XAML which I can change via ToggleButton.

1 Employee class where a ObservableCollection<Groups> is located and inside of the Groups.Col there is a ObservableCollection<Rights> which contains the default group rights which was loaded from DataBase which cant be changed.

Note: My get set is always the same. They just have other names and DataTypes consider to its field datatype.

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).

Employee Class

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).
}

Rights Class

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

// Again get set is same

Groups Class

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

// Again, same Get/Set like always

XAML

In my XAML I have: a ComboBox. ComboBox.ItemsSource bind to GroupsCollection. ComboBox.SelectedValue bind to SingleEmployee.Group.

So while changing the ComboBox, the Group of the Single Employee will be set.

This ComboBox also got an SelectionChanged Event where I set the RightsCollection equal to SingleEmployee.Group.Rights. So that both contains the same items/values now.

It also contains an ItemsControl where I can set the rights myself (and where the rights will be loaded when ComboBox.SelectionChanged (which works).

<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 Event in Code-Behind

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("################################################");

Set ViewModel in Code-Behind

private readonly EmployeeViewModel _viewModel;

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

Save Button Command Method

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");

What I tried

SelectionChanged Event

// 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);

Result of the Debugging

SelectionChangedResult SelectionChangedResult (GIF) |

SelectionChangedResult SelectionChangedResult (Picture)

After Button Click After Button Click (GIF)

After Button Click After Button Click (Picture)

Upvotes: 0

Views: 104

Answers (2)

Pielroja
Pielroja

Reputation: 35

I fixed this problem in my SelectionChanged Event deleting this line:

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

and replaced it with this:

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;
    }
}

Because both collections are nearly the same, they will always have the same amount of items so I can use a for-loop. If a value is not the same, then the value will change.

This way I don't create a reflection (I guess) so it's working.

The only thing now is, that

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

isn't working but I will use a for-loop here too which checks if the items contains the same value, if not then "Something changed".

Upvotes: 0

Jos&#233;
Jos&#233;

Reputation: 21

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

the left collection has the same reference of the right collection. So, if you change one collection it will reflect in the other collection.

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

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

Upvotes: 2

Related Questions