【问题标题】:How to achieve dynamic binding in WPF/MVVC C#如何在 WPF/MVVM C#​​ 中实现动态绑定
【发布时间】:2017-11-02 15:48:02
【问题描述】:

我对 MVVC/wpf 比较陌生,主要使用 winforms。

我想要完成的是动态数据绑定,而不使用 WPF 中的代码。用户界面由一个 devexpress 网格和几个按钮组成。每次按下按钮都会加载一个对象列表并在网格中显示对象。列表包含不同的对象类型,具体取决于按下的按钮。对于这个例子,我有两个类要展示:FatCat 和 FatDog。

在 winforms 中这有效:

    private void button1_Click(object sender, EventArgs e)
    {
        ((GridView)gridCtrl.MainView).Columns.Clear();
        gridCtrl.DataSource = new BindingSource(itsModel.GetAll<FatDog>(), null);
    }


    private void button2_Click(object sender, EventArgs e)
    {
        ((GridView)gridCtrl.MainView).Columns.Clear();
        gridCtrl.DataSource = new BindingSource(itsModel.GetAll<FatCat>(), null);
    }

我已将网格配置为动态创建列,因此一切正常。 itsModel 是 CatClientModel 类型。

在 wpf 中,我将 DataContext 定义为 CatClientModel。

我应该为网格中的 ItemsSource 使用什么来实现与我的 winforms 解决方案相同的行为?

dxg:GridControl ItemsSource="{Binding SomeDynamicList}"

换句话说,SomeDynamicList 在上面的代码中应该是什么?还是我走错了路?

正如我所说,我正在使用 DevExpress wpf 网格控件,但问题应该是一般性的,适用于任何呈现对象列表的控件。

【问题讨论】:

    标签: c# .net wpf


    【解决方案1】:

    换句话说,SomeDynamicList 在上面的代码中应该是什么?

    SomeDynamicList 应该是一个ObservableCollection&lt;T&gt; 属性,您可以向其中添加任何您想在GridControl 中显示的T 类型的对象。

    GridControlDataContext 或其任何父元素设置为定义此属性的类的实例:

    public class CatClientModel
    {
        public ObservableCollection<Animal> SomeDynamicList { get; } = new ObservableCollection<Animal>();
    }
    
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new CatClientModel();
        }
    }
    

    好的。但问题是 ObservableCollection 包含不同的类型。不幸的是,没有可行的类可以继承。我想根据按下的按钮绑定到 ObservableCollection 或 ObservableCollection

    然后切换DataContext,或将属性更改为IEnumerable,并在每次单击按钮时将其设置为新集合。这需要您在视图模型中实现INotifyPropertyChanged 接口

    private System.Collections.IEnumerable _collection;
    public System.Collections.IEnumerable MyProperty
    {
        get { return _collection; }
        set { _collection = value; OnPropertyChanged(); }
    }
    

    【讨论】:

    • 好的。但问题是 ObservableCollection 包含不同的类型。如果您与我的 winforms 示例进行比较,则每个按钮都会创建一个新的强类型列表。不幸的是,没有可行的类可以继承。我正在做的实际项目与动物无关,这只是一个例子。所以绑定到 ObservableCollection 并不能解决问题。我想根据按下的按钮绑定到 ObservableCollection 或 ObservableCollection
    • 然后切换DataContext,或将属性更改为IEnumerable,并在每次单击按钮时将其设置为新集合。这需要您在视图模型中实现 INotifyPropertyChanged 接口。
    • 有没有办法改变 DataContext 而无需后面的代码?将属性更改为 IEnumerable 对我有何帮助?
    • 1.No. 2. 您可以将 IEnumerable 属性设置为 ObservableCollection 或 ObservableCollection
    • 我不明白 2 是如何工作的。 IEnumerable 还需要声明时的类型。还是?
    【解决方案2】:

    如果您想使用 XAML 为每个可能的网格定义您的代码映射到哪些数据源。这确实需要至少某种 MVVM 管理器方法(prism 或 mvvmlight)将视图模型连接到视图。

    因此,如果您确实采用 MVVM 模型路线,模型将包含对您的每个网格的描述,如下所示:

     public BulkObservableCollection<icd10facet> FacetList
        {
            get { return this._facets; }
            set { SetProperty(ref this._facets, value); }
    
        }
        public INotifyTaskCompletion<BulkObservableCollection<PetsConvert>> ConceptList
        {
            get { return this._concept; }
            set
            {
                SetProperty(ref this._concept, value);
            }
        }
    

    在您的代码的 XAML 中,网格会以这种方式绑定到由 ConceptList 定义的网格:

    ItemsSource="{Binding ConceptList.Result}" 
    

    此答案未解决如何连接 Prism 6.0 以使用视图模型,但示例请参见:

    https://github.com/PrismLibrary/Prism

    其中包含文档和入门代码。请记住,将代码放在视图后面的代码中没有任何具体原因是一个问题,首先解决问题,然后如果关注点分离对您来说是一个问题,则进行重构。

    使用这种技术,您可以将每个网格绑定到其自己的数据源。在 MVVM 空间按钮和其他东西使用命令模型与视图模型进行通信。

     <Button Content="Load Rule Data" Width="100" Height="40" HorizontalAlignment="Left" Margin="5px" Command="{Binding LoadRuleData }"/>
    

    这需要在视图模型中为 LoadRuleData 定义一个命令委托

        public DelegateCommand LoadRuleData { get; private set; }
    

    然后(通常在构造函数中)将 DelegateCommand 连接到将要完成工作的方法。

     this.LoadRuleData = new DelegateCommand(this.loadRules);
    

    【讨论】:

      猜你喜欢
      • 2013-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多