wpf 将命名元组绑定到XAML DataGrid

sulc1iza  于 2023-04-13  发布在  其他
关注(0)|答案(1)|浏览(204)

在我的WPF应用程序中,我有很多视图模型,现在需要一个“属性值”,比如grid。
我试图构建一个通用的视图模型,可以“注入”现有的视图模型,这样我就可以毫不费力地将它们用于新窗口。为此,我编写了一个带有可观察集合的简单接口:

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

并且,在需要新属性值网格的其中一个视图模型中:

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

遵循现有的应用惯例:

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

现在,在我的常规XAML对话框中出现了问题:

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

这是正确的:在运行时,我有绑定错误,告诉我“属性Prop在类型ValueTuple'2的对象中未找到”和“属性Val在类型ValueTuple'2的对象中未找到”,但我不知道为什么。
有什么提示吗?

lp0sw83n

lp0sw83n1#

名称PropVal只有在编译之前才真正存在。它们实际上被命名为Item1Item2。编译器做了一些魔术,让你在源代码中使用更好的名称。然而,这些是字段而不是属性,你可能需要在WPF中绑定属性。我建议你只添加自己的类:

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

如果你愿意的话,可以从相应的valuetuple中添加一个隐式或显式的转换。

相关问题