0

Maybe this is a bad design idea, but this is what I had in mind:

public class NetworkDrive : BaseNotify
{
    private char letter;
    public char Letter
    {
        get => letter;
        set => SetAndNotify(ref letter, value, nameof(Letter));
    }

    private string name;
    public string Name
    {
        get => name;
        set => SetAndNotify(ref name, value, nameof(Letter));
    }

    private bool isLetterAvailable;
    public bool IsLetterAvailable
    {
        get => isLetterAvailable;
        set => SetAndNotify(ref isLetterAvailable, value, nameof(Letter));
    }
}

public class EditDriveViewModel : Screen
{
    public ObservableCollection<NetworkDrive> NetworkDrives { get; } = new();

}

NetworkDrives is filled with all the alphabet letters and when the user selects a letter and names it, the letter is no longer available so IsLetterAvailable is set to false.

I would like to list it in a datagridview but only the letters that are in use, i.e.: letters with IsLetterAvailable set to false, but if I use ItemsSource to NetworkDrives it will list everything.

If I do something like the below:

public ObservableCollection<NetworkDrive> UsedNetworkDrives
{
    get => NetworkDrives.Where(x => !x.IsLetterAvailable).ToList();
}

Then I lose notifications and the ability of being able to set a letter to true/false and have it reflected.

In the datagridview I also have a combobox on letter, so that the user can change it, so I also need to manage it so that used letters are displayed in red and the user cannot use then if selected.

Is there a way to solve this?

Guapo
  • 3,446
  • 9
  • 36
  • 63
  • Sorry I don't speak your language – Guapo Sep 24 '21 at 16:34
  • Sorry. I didn’t notice that I posted in a language other than English. Please be clear: Are you using Forms.DadaGridView or Controls.DataGrid (WPF)? If the latter, how did you bind the DataGrid to your NetworkDrives collection? – EldHasp Sep 24 '21 at 16:42
  • I am using Stylet, so MVVM, `{Binding NetworkDrives}` and as I tagged the question its WPF – Guapo Sep 24 '21 at 17:07

1 Answers1

1

If you don't want to touch the source collection in the view model, you could use a filtered CollectionViewSource in the view:

<Window.Resources>
    <CollectionViewSource x:Key="cvs" Source="{Binding NetworkDrives}"
                              Filter="CollectionViewSource_Filter"
                              IsLiveFilteringRequested="True"
                              xmlns:s="clr-namespace:System;assembly=mscorlib">
        <CollectionViewSource.LiveFilteringProperties>
            <s:String>IsLetterAvailable</s:String>
        </CollectionViewSource.LiveFilteringProperties>
    </CollectionViewSource>
</Window.Resources>
...
<ComboBox x:Name="cmb"
          ItemsSource="{Binding Source={StaticResource cvs}}"
          DisplayMemberPath="Name" />

    private void CollectionViewSource_Filter(object sender, FilterEventArgs e) =>
        e.Accepted = e.Item is NetworkDrive networkDrive
          && networkDrive.IsLetterAvailable;
mm8
  • 163,881
  • 10
  • 57
  • 88
  • Thats a great idea but will the filter update if an item is added to the NetworkDrives or I need to refresh it or something? – Guapo Sep 24 '21 at 16:33
  • Yes. Will be if NetworkDrives is an observable collection and its change notification is correctly implemented. Your best bet is to make NetworkDrives read-only. That is, so that the property does not have a setter. – EldHasp Sep 24 '21 at 16:46
  • By the way, in the code of your question, NetworkDrives is a field, not a property. But binding cannot work with fields. Correct it with the following code: `public ObservableCollection NetworkDrives {get;}= new();`. – EldHasp Sep 24 '21 at 16:50
  • Yeah that was a typo, thanks for noticing, interesting I can definitively make it readonly I will give it a go thanks. – Guapo Sep 24 '21 at 17:08
  • That worked really well, thanks. Would you say using the filtering for this purpose a bad design or that I could have done this differently? – Guapo Sep 25 '21 at 10:42