【问题标题】:Selection change in DataGrid ComboBox template column clears values in other rowsDataGrid ComboBox 模板列中的选择更改会清除其他行中的值
【发布时间】:2016-07-27 10:46:56
【问题描述】:

在我的项目中,我有一个DataGrid,其中有两个模板列,每个列都包含一个ComboBox。当我在任何行中更改ComboBox 之一的选择时,更改会反映在所有行中。

我试过设置IsSynchronizedWithCurrentItem="False",但这没有帮助。

谁能给我一个解决这个问题的方法?这是我的代码。

Xaml

<DataGrid 
        x:Name="dtg"
        CanUserAddRows="False"
        AutoGenerateColumns="False"
        IsSynchronizedWithCurrentItem="False"
        ItemsSource="{Binding Pdts, Mode=TwoWay}">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Type" Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox
                            IsEditable="True"
                            ItemsSource="{Binding DataContext.TypeCollection, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                            DisplayMemberPath="TypeName"
                            SelectedItem="{Binding Type}"
                            SelectedValuePath="Id"
                            SelectionChanged="ComboBox_SelectionChanged_1"
                            SelectedValue="{Binding TypeId, Mode= TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

            <DataGridTemplateColumn Header="Name" Width="*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox
                            IsEditable="True"
                            KeyUp="ComboBox_KeyUp_1"
                            IsSynchronizedWithCurrentItem="False"
                            ItemsSource="{Binding DataContext.PdtCollection, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                            DisplayMemberPath="PdtName"
                            SelectedItem="{Binding Pdt}"
                            SelectedValuePath="Id"
                            SelectedValue="{Binding Id, Mode= TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>

视图模型

public class MainWindowViewModel : Base {
    public ObservableCollection<Type> TypeCollection { get; set; }
    public ObservableCollection<Pdt> PdtCollection { get; set; }
    public ObservableCollection<PdtAndType> Pdts { get; set; }

    public MainWindowViewModel() {
        TypeCollection = new ObservableCollection<Type>();
        PdtCollection = new ObservableCollection<Pdt>();
        Pdts = new ObservableCollection<PdtAndType>();

        TypeCollection.Add(new Type {Id = 1, TypeName = "one"});
        TypeCollection.Add(new Type {Id = 2, TypeName = "two"});
        TypeCollection.Add(new Type {Id = 3, TypeName = "three"});
        TypeCollection.Add(new Type {Id = 4, TypeName = "four"});
        TypeCollection.Add(new Type {Id = 5, TypeName = "five"});

        addPdt();
    }

    public void add(int typeId = 1) {
        Random r = new Random();
        int x = r.Next(10);
        PdtCollection.Clear();
        for (int i = 0; i < x; i++) {
            PdtCollection.Add(new Pdt {Id = 1, PdtName = "P" + i + 1});
        }
    }

    public void addPdt() {
        Pdts.Add(new PdtAndType());
    }
}

模型类Pdt

public class Pdt : Base {
    private int _ID;

    public int Id {
        get { return _ID; }
        set {
            if (_ID != value) {
                _ID = value;
                onPropertyChanged("Id");
            }
        }
    }

    private String _PdtName;

    public String PdtName {
        get { return _PdtName; }
        set {
            if (_PdtName != value) {
                _PdtName = value;
                onPropertyChanged("PdtName");
            }
        }
    }

    private int _typeId;

    public int TypeId {
        get { return _typeId; }
        set {
            if (_typeId != value) {
                _typeId = value;
                onPropertyChanged("TypeId");
            }
        }
    }
}

模型类类型

public class Type : Base {
    private int _ID;

    public int Id {
        get { return _ID; }
        set {
            if (_ID != value) {
                _ID = value;
                onPropertyChanged("Id");
            }
        }
    }

    private String _typeName;

    public String TypeName {
        get { return _typeName; }
        set {
            if (_typeName != value) {
                _typeName = value;
                onPropertyChanged("TypeName");
            }
        }
    }
}

模型类PdtAndtype

 public class PdtAndType : Base {
    private int _typeId;

    public int TypeId {
        get { return _typeId; }
        set {
            if (_typeId == value) return;
            _typeId = value;
            onPropertyChanged(nameof(TypeId));
        }
    }

    private int _pdtId;

    public int PdtId {
        get { return _pdtId; }
        set {
            if (_pdtId == value) {
                return;
            }
            _pdtId = value;
            onPropertyChanged(nameof(PdtId));
        }
    }

    private Type _type;

    public Type Type {
        get { return _type; }
        set {
            if (_type == value) {
                return;
            }
            _type = value;
            onPropertyChanged(nameof(Type));
        }
    }

    private Pdt _pdt;

    public Pdt Pdt {
        get { return _pdt; }
        set {
            if (_pdt == value) {
                return;
            }
            _pdt = value;
            onPropertyChanged(nameof(Pdt));
        }
    }
}

【问题讨论】:

    标签: c# wpf combobox datagrid datagridtemplatecolumn


    【解决方案1】:

    您似乎正在将 SelectedItem 绑定到 ViewModel 上的同一对象。

    我猜你没有发布整个 ViewModel,但这是我能得出的唯一结论。

    我建议你为每一行制作模型,其中包含一个 SelectedType 和一个 SelectedPdt 属性。

    如果您发布有关 ViewModel 和模型的更多详细信息,我会很乐意详细说明。


    编辑

    好的,我现在可以看到问题了。

    您的组合框仅使用了 1 个 ViewModel。 在您的 KeyUp 事件处理程序中,您替换 PdtCollection 中的项目。

    这个集合是单一的,所有的组合框都绑定到这个单一的集合。 如果我了解您的目标,您希望为每一行制作不同的集合。

    由于 DataGrid 中的一行由 Pdts 集合表示,我建议您将 PdtCollection 放在里面 你的 Pdt 对象。这样,您可以将每行的组合框绑定到行模型内的相关集合。

    为了让事情更简单, 你的 Pdt 应该看起来像这样:

    class Pdt : Base
    {
        /* 
            Other properties
        */
    
        private ObservableCollection<Pdt> _pdts;
        public ObservableCollection<Pdt> Pdts
        {
            get { return _pdts; }
            set { _pdts = value; }
        }
    }
    

    之后,您可以将您的列绑定到 Window 的 DataContext 中的单个集合上,而不是绑定到 ROW 数据上下文。这应该看起来像这样:

    <DataGridTemplateColumn Header="Name" Width="*">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <ComboBox IsEditable="True"
                          KeyUp="ComboBox_KeyUp_1"
                          IsSynchronizedWithCurrentItem="False"
                          ItemsSource="{Binding PdtCollection}"
                          DisplayMemberPath="PdtName"
                          SelectedItem="{Binding Pdt}"
                          SelectedValuePath="Id"
                          SelectedValue="{Binding Id, Mode= TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
    

    我认为您需要稍微调整一下代码(选择和显示的成员等,当然还要将内部 PdtCollection 初始化为您想要的任何值),但总体思路是这个。

    我希望我已经足够清楚了。 快乐编码。 :)

    【讨论】:

    • 我已经编辑了我的问题,如果你想看的话,我可以分享整个项目。并感谢您的时间:-)
    • 这里是link
    • 答案已编辑。我希望我足够清楚。快乐编码! :)
    • 谢谢 :-) 这行得通,虽然有一点内存开销,没关系
    猜你喜欢
    • 2018-04-15
    • 2015-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多