【问题标题】:wpf toolkit data gridwpf 工具包数据网格
【发布时间】:2009-06-08 20:48:38
【问题描述】:

你好,我正在构建一个带有数据网格的 wpf 应用程序, 模式是模型视图视图模型。

我的所有屏幕都包含一个内容控件,我只是为他分配了具有合适数据模板的视图模型,

无论如何,我的问题在于组合框列,数据上下文是呈现的实体,我需要它作为视图模型。

什么是最好的解决方案?

【问题讨论】:

    标签: wpf wpf-controls wpftoolkit


    【解决方案1】:

    我正在使用另一个数据网格,但它可能是相似的。我的做法是这样的:

    在 XAML 中,我在资源中定义了一个 ObjectDataProvider:

    <ObjectDataProvider x:Key="VM" ObjectInstance="{x:Null}" x:Name="vm"/>
    

    然后在分配 DataContext(构造函数或 DataContextChanged 事件)之后,我这样做了:

    (this.Resources["VM"] as ObjectDataProvider).ObjectInstance = this.DataContext;
    

    在 Combobox xaml 中,我将其用作绑定源:

    ItemsSource="{Binding Source={StaticResource VM}, Path=SomeItems, Mode=OneWay}"
    

    不确定它是否适用于 microsoft datagrid,但我想值得一试。

    【讨论】:

    • 是的。据我所知,这两个项目都不是视觉树的直接部分,所以这样的事情可能会做到。
    【解决方案2】:

    这就是我将 ViewModel 与 ComboBoxes 一起使用的方式,DataContext 是 ViewModel,而不是底层实体 (List)。

    ViewModel(Person 是一个具有 Name 和 Age 的 Simple 类):

    public class PeopleViewModel : INotifyPropertyChanged
    {
        private List<Person> _peopleList;
        private Person _selectedPerson;
    
        public PeopleViewModel()
        {
            // initialize with sample data
            _peopleList = getPeopleList();
        }
    
        // gets sample data
        private List<Person> getPeopleList()
        {
            var result = new List<Person>();
            for (int i = 0; i < 10; i++)
            {
                result.Add(new Person("person " + i, i));
            }
            return result;
        }
    
        public List<Person> PeopleList
        {
            get { return _peopleList; }
        }
    
        public Person SelectedPerson
        {
            get { return _selectedPerson; }
            set
            {
                if (_selectedPerson == value) return;
                _selectedPerson = value;
                // required so that View know about changes
                OnPropertyChanged("SelectedPerson");
            }
        }
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        // WPF will listen on this event for changes
        public event PropertyChangedEventHandler PropertyChanged;
    }
    

    组合框的 XAML:

    <ComboBox Name="cmbEnum" Width="150" ItemsSource="{Binding Path=PeopleList}" SelectedValue="{Binding Path=SelectedPerson}" SelectedValuePath="" DisplayMemberPath="Name" ></ComboBox>
    

    在后面的代码中我可以做到:

        public Window2()
        {
            InitializeComponent();
    
            vm = new PeopleViewModel();
            // we are listening on changes of ViewModel, not ComboBox
            vm.PropertyChanged += new PropertyChangedEventHandler(vm_PropertyChanged);
            this.DataContext = vm;
        }
    
        void vm_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
        if (e.PropertyName == "SelectedPerson")
        {
            MessageBox.Show(vm.SelectedPerson.Age.ToString());
        }
        }
    
        // button1_Click should be probably replaced by Command
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            // sample showing that GUI is updated when ViewModel changes
        vm.SelectedPerson = vm.PeopleList[2];
        }
    

    希望这会有所帮助,我对 WPF 很陌生,如果这是使用 MVVM 的正确方法,我想听听任何反馈,我认为它非常优雅,因为您只在代码中处理 ViewModel 和 Model,并且可以替换视图。

    【讨论】:

      【解决方案3】:

      我发现实现这一点的最佳方法是为我在网格中使用的所有查找定义一些外部类,并将它们作为静态资源嵌入到模板中

      【讨论】:

        【解决方案4】:

        我们最终为每个组合框列表创建了具有静态属性的类:

        (您不能将类本身设为静态,否则 XAML 将无法打开它,但不会出现编译错误)

        例如:

        public class ZoneList
        {
          private static readonly IList<Zone> _Items = new List<Zone>();
          public static IList<Zone> Items
          {
            get { return _Items; }
          }
        }
        

        然后在 XAML 中:

        <UserControl.Resources>
            <ResourceDictionary>
                <ObjectDataProvider x:Key="myZoneList"   ObjectType="{x:Type StaticLists:ZoneList}"/>
            </ResourceDictionary>
        </UserControl.Resources>
        
        <ComboBox ItemsSource="{Binding Path=Items, Source={StaticResource myZoneList}}"></ComboBox>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-12-19
          • 2010-12-13
          • 1970-01-01
          • 2010-11-26
          • 1970-01-01
          • 2011-06-15
          • 2010-12-06
          • 1970-01-01
          相关资源
          最近更新 更多