将DataGridComboBoxColumn值传递给ObjectDataProvider';s MethodPa

本文关键字:MethodPa ObjectDataProvider DataGridComboBoxColumn 值传 | 更新日期: 2023-09-27 18:20:58

我在一个DataGrid中有两个DataGridComboBoxColumns(技术上是DataGridTemplateColumns)。我正在使用MVVM。

第一列的ItemsSource绑定到了一个静态资源,这没有问题。

第二列的ItemsSource取决于第一列选择的值。第一列的值(SelectedValue)作为MethodParameter传递给ObjectDataProvider。ObjectDataProvider是第二列的ItemsSource。

使用第一列的SelectedValue作为ObjectDataProvider的MethodParameter的问题是当我在DataGrid中插入第二行时。如果第二行在列1中使用的值与在第一行的列1中不同,则它将清除第一行的第2列值(因为新的SelectedValue更改了ObjectDataProvider提供的可供选择的项列表)。

我真的很想把第一列的Text值作为其MethodParameter传递给ObjectDataProvider,但当第一列的Text值已经绑定到更新我的模型时,我该怎么做呢?

以下是我的问题XAML的摘录:

<!--
My ObjectDataProvider. It returns a collection of strings for the user to choose from via the second DataGridTemplateColumn.
The first DataGridTemplateColumn feeds ObjectDataProvider a MethodParameter. 
The method is simple. It looks like:
    public List<String> ProductLineCategoryList_CategoryCodes(string productLineCode)
    {
        // return a list of strings based from an object collection, filtered by the passed in argument.
    }
-->
<ObjectDataProvider x:Key="categoryCodes" ObjectType="{x:Type e:ItemsProvider}" MethodName="ProductLineCategoryList_CategoryCodes">
    <ObjectDataProvider.MethodParameters>
        <x:StaticExtension Member="sys:String.Empty"/>
    </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<!-- 
This DataGridComboBoxColumn lets the user choose a ProductLineCode.
Its SelectedValue provides a string value for the ObjectDataProvider's MethodParameter.
The ObjectDataProvider is used as the ItemsSource for the DataGridComboBoxColumn
below this one.
The problem with using SelectedValue to feed ObjectDataProvider a MethodParameter, when
a second row is added to my DataGrid and the second row uses a different ProductLineCode than
the first row, it clears the first row's ProductLineCategoryCode value.
-->
<DataGridTemplateColumn 
    Header="Product Line"
    ClipboardContentBinding="{Binding ProductLineCode}">
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <ComboBox
                IsEditable="True"
                ItemsSource="{x:Static e:ItemsProvider.ProductLineCategoryList_ProductLineCodeList}"
                SelectedValue="{Binding Source={StaticResource categoryCodes}, 
                                Path=MethodParameters[0], BindsDirectlyToSource=True, 
                                UpdateSourceTrigger=PropertyChanged}"
                Text="{Binding ProductLineCode, UpdateSourceTrigger=PropertyChanged}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>                                               
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ProductLineCode}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>              
</DataGridTemplateColumn>
<!-- 
This DataGridComboBoxColumn uses the ObjectDataProvider for its ItemsSource.
ItemsSource s/b limited by the selection made from the above DataGridComboBoxColumn.
-->
<DataGridTemplateColumn 
    Header="Product Line Cat"
    ClipboardContentBinding="{Binding ProductLineCategoryCode}">
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <ComboBox 
                IsEditable="True"
                ItemsSource="{Binding Source={StaticResource categoryCodes}}"
                Text="{Binding ProductLineCategoryCode, UpdateSourceTrigger=PropertyChanged}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>                                               
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ProductLineCategoryCode}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>              
</DataGridTemplateColumn>                                           

我已经引用了net来寻求帮助,但我找不到适合我的解决方案。我只需要传递一个字符串,而不需要传递对象(尽管我想我可以更改ObjectDataProvider的方法来接受对象,然后这可能会起作用)。如果这不是一个DataGrid,这个MSDN解决方案将非常有效。

将DataGridComboBoxColumn值传递给ObjectDataProvider';s MethodPa

IMHO您试图在XAML中做太多事情。

你最好利用你的虚拟机。

以下是一个模拟您的模型和情况的示例:

企业/VM实体:

public class Product : INotifyPropertyChanged
{
    private static readonly IDictionary<string, string[]> catalog = new Dictionary<string, string[]>
    {
        { "Fruit", new[]{ "Apple", "Banana", "Cherry" } },
        { "Vegatable", new[]{ "Amaranth", "Broccolini", "Celery" } }
    };
    public static IDictionary<string, string[]> Catalog { get { return catalog; } }
    private string productLineCategoryCode;
    public string ProductLineCategoryCode
    {
        get { return productLineCategoryCode; }
        set
        {
            if (value != productLineCategoryCode)
            {
                productLineCategoryCode = value;
                PropertyChanged(this, new PropertyChangedEventArgs("ProductLineCategoryCode"));
                PropertyChanged(this, new PropertyChangedEventArgs("ProductLineCodes"));
            }
        }
    }
    public IEnumerable<string> ProductLineCodes
    {
        get
        {
            return Catalog[ProductLineCategoryCode];
        }
    }
    private string productLineCode;
    public string ProductLineCode
    {
        get { return productLineCode; }
        set
        {
            if (value != productLineCode)
            {
                productLineCode = value;
                PropertyChanged(this, new PropertyChangedEventArgs("ProductLineCode"));
            }
        }
    }
    public event PropertyChangedEventHandler PropertyChanged = delegate { };
}

ProductLineCodes是给定类别的可用代码列表,您只需绑定到它即可

因此,当用户更改类别时,我们会通知它和可用代码列表都已更改。

视图:

<DataGrid ItemsSource="{Binding Products}" CanUserAddRows="True" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Product Line Cat"
                                ClipboardContentBinding="{Binding ProductLineCategoryCode}">
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <ComboBox IsEditable="True"
                                ItemsSource="{Binding Path=(local:Product.Catalog).Keys}"
                                SelectedValue="{Binding ProductLineCategoryCode, UpdateSourceTrigger=PropertyChanged}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding ProductLineCategoryCode}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Product Line" ClipboardContentBinding="{Binding ProductLineCode}">
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <ComboBox IsEditable="True"
                                ItemsSource="{Binding ProductLineCodes}"
                                SelectedValue="{Binding ProductLineCode,UpdateSourceTrigger=PropertyChanged}">                                
                    </ComboBox>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding ProductLineCode}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

我可以想象使用IValueConverter的另一个变体,但我希望这个变体对您的用例来说足够好。。。