Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Binding named tuple to XAML DataGrid

In my WPF application, I have a lot of view models that, now, require a "property-value" like grid.

I’m trying to build a generic purpose view model that can be "injected" in existing ones so that I can use them with the new window with little no effort. To do this, I’ve written a simple interface with an observable collection:

public interface IPropertyGridVM
{
    ObservableCollection<(string Prop, object Val)> PropValueList
    {
        get;
        set;
    }
}

And, in one of the View Models that needs the new property-value grid:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

public class ExistingVM : ViewModelBase<Model>, IPropertyGridVM
{
    public ObservableCollection<(string Prop, object Val)> PropValueList
    {
        get;
        set;
    }

    ExistingVM()
         : base(new Model())
    {
        // "old" vm initialization
        initPropValueList();
    }

    ExistingVM(Model model)
         : base(model)
    {
        // "old" vm initialization
        initPropValueList();
    }

    private void initPropValueList()
    {
         PropValueList = new ObservableCollection<(string Prop, object Val)>()
         {
             (nameof(Prop1), Prop1),
             // ...
         }
    }
}

Following the existing convention of the application:

// This piece of code is inside a Dialog Manager    
public void ShowPropertiesDialog<T>(T propValueLikeVm)
{
    if (propValueLikeVm is IPropertyGridVM)
    {
        // create the dialog
        PropertyGridDialog dialog = new PropertyGridDialog();
        // assign the datacontext
        dialog.DataContext = propValueLikeVm;
        // till here is all ok, VM is correctly initialized and contains what I expected
        dialog.ShowDialog();
    }
}

Now, in my general XAML dialog come the troubles:

<...
     xmlns:vm="clr-namespace:ViewModels;assembly=ViewModels"
     d:DataContext="{d:DesignData Type={x:Type vm:IPropertyGridVM},
                             IsDesignTimeCreatable=True}"
     mc:Ignorable="d">
<!-- dialog styling and definition -->
<!-- Intellisense warns me of some problems in binding the PropValueList: "No DataContext value found for PropValueList"-->
<DataGrid ItemsSource="{Binding Path=PropValueList}">
     <DataGrid.Columns>
            <DataGridTextColumn Width="2*" Binding="{Binding Path=Prop}">
                   <!-- Text column styling -->
            </DataGridTextColumn>
            <DataGridTextColumn Width="2*" Binding="{Binding Path=Val}">
                   <!-- Text column styling -->
            </DataGridTextColumn>
     </DataGrid.Columns>
</DataGrid>

And it’s right: at run-time I have binding errors that tell me that "The property Prop has not been found in the object of type ValueTuple’2" and "The property Val has not been found in the object of type ValueTuple’2", but I can’t figure why.

Any hints?

>Solution :

The names Prop and Val are only really present before compilation. They are really named Item1 and Item2. The compiler does some magic to let you use better names in the source. However, these are fields and not properties, and you might need properties to bind to in WPF. I would recommend just adding your own class:

public class PropVal : INotifyPropertyChanged{
    public string Prop {get;}
    public object Val {get;}
    public PropVal(string prop, object val) => (Prop, Val) = (prop, val);
    public event PropertyChangedEventHandler PropertyChanged;

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

I would expect that to be more reliable. Add a implicit or explicit conversion from the corresponding valuetuple if you wish.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading