如何使用纯MVVM概念和依赖注入将WPF页面上不同集合的不同面板上可用的XamDataGrid绑定。

问题描述:

我有一个WPF XAML页面,有3个部分由DockPanels分隔。一个面板包含与集合绑定的INFRAGITICS XamDataGrid控件。如何使用纯MVVM概念和依赖注入将WPF页面上不同集合的不同面板上可用的XamDataGrid绑定。

  1. 我想以纯MVVM方式使用DataContext/DataSource属性绑定XamDataGrid控件。
  2. 此外,倒很理解,如果结合是通过依赖注入来完成。

我曾尝试不同的方法,但没有获得成功。我粘贴了以下代码以供参考。请帮助。

XAML页面:

<Window x:Class="UserInterface.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:UserInterface" 
     xmlns:igDP="clr-namespace:Infragistics.Windows.DataPresenter;assembly=InfragisticsWPF.DataPresenter" 
      xmlns:igEditors="clr-namespace:Infragistics.Windows.Editors;assembly=InfragisticsWPF.Editors" 
      xmlns:sys="clr-namespace:System;assembly=mscorlib" 
     xmlns:dc ="clr-namespace:UserInterface.ViewModel" 
     xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase" 
     mc:Ignorable="d" 
     Title="MainWindow"> 
    <Window.Resources> 
     <dc:GraphicViewModel x:Key="dataContext"/> 
    </Window.Resources> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height=".5*"/> 
      <RowDefinition Height=".5*"/> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width=".5*"/> 
      <ColumnDefinition Width=".5*"/> 
     </Grid.ColumnDefinitions> 

     <DockPanel Grid.Column="0" Grid.Row="0"> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="Auto"/> 
        <ColumnDefinition Width="Auto"/> 
        <ColumnDefinition Width="Auto"/> 
       </Grid.ColumnDefinitions> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="Auto"/> 
        <RowDefinition Height="Auto"/> 
        <RowDefinition Height="Auto"/> 
        <RowDefinition Height="Auto"/> 
        <RowDefinition Height="Auto"/> 
       </Grid.RowDefinitions> 
      </Grid> 
      <!--<StackPanel Orientation="Vertical" DockPanel.Dock="Top"> 
       <StackPanel Orientation="Horizontal" Margin="5" Grid.Row="0"> 
        <DockPanel> 
         <TextBlock Text="*.cfg File" Grid.Column="0" DockPanel.Dock="Left"/> 
         <Button Content="Browse..." Grid.Column="2" DockPanel.Dock="Right"/> 
         <TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.cfg file..." Grid.Column="1" DockPanel.Dock="Right"/> 
        </DockPanel> 
       </StackPanel> 
       <StackPanel Orientation="Horizontal" Margin="5" Grid.Row="1"> 
        <TextBlock Text="*.ps File " Grid.Column="0"/> 
        <TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.ps file..." Grid.Column="1"/> 
        <Button Content="Browse..." Grid.Column="2"/> 
       </StackPanel> 
       <StackPanel Orientation="Horizontal" Margin="5" Grid.Row="2"> 
        <TextBlock Text="*.pic File " Grid.Column="0"/> 
        <TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.pic file..." Grid.Column="1"/> 
        <Button Content="Browse..." Grid.Column="2"/> 
       </StackPanel> 
       <StackPanel Orientation="Horizontal" Margin="5" Grid.Row="3"> 
        <TextBlock Text="*.xlsx File" Grid.Column="0"/> 
        <TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.xlsx file..." Grid.Column="1"/> 
        <Button Content="Browse..." Grid.Column="2"/> 
       </StackPanel> 
       <StackPanel Orientation="Horizontal" Margin="5" Grid.Row="4"> 
        <TextBlock Text="*.xlsx File"/> 
        <TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.xlsx file..." Grid.Column="1"/> 
        <Button Content="Browse..." Grid.Column="2"/> 
       </StackPanel> 
      </StackPanel>--> 
      <StackPanel Orientation="Horizontal"> 
       <StackPanel Orientation="Vertical" Margin="5" Grid.Row="0"> 
        <TextBlock MinHeight="20.5" Text="*.cfg File" Grid.Column="0"/> 
        <TextBlock MinHeight="20.5" Text="*.ps File " Grid.Column="0"/> 
        <TextBlock MinHeight="20.5" Text="*.pic File " Grid.Column="0"/> 
        <TextBlock MinHeight="20.5" Text="*.xlsx File" Grid.Column="0"/> 
        <TextBlock MinHeight="20.5" Text="*.xlsx File" Grid.Column="0"/>     
       </StackPanel> 
       <StackPanel Orientation="Vertical" Margin="5" Grid.Row="1"> 
        <TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.cfg file..." Grid.Column="1" MinHeight="20.5"/> 
        <TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.ps file..." Grid.Column="1" MinHeight="20.5"/> 
        <TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.pic file..." Grid.Column="1" MinHeight="20.5"/> 
        <TextBox FontStyle="Italic" FontWeight="Light" Text="Browse Model mapping file..." Grid.Column="1" MinHeight="20.5"/> 
        <TextBox FontStyle="Italic" FontWeight="Light" Text="Browse Parameter mapping file..." Grid.Column="1" MinHeight="20.5"/>     
       </StackPanel> 
       <StackPanel Orientation="Vertical" Margin="5" Grid.Row="2"> 
        <Button Content="Browse..." Grid.Column="2"/> 
        <Button Content="Browse..." Grid.Column="2"/> 
        <Button Content="Browse..." Grid.Column="2"/> 
        <Button Content="Browse..." Grid.Column="2"/> 
        <Button Content="Browse..." Grid.Column="2"/> 
       </StackPanel>    
      </StackPanel> 
     </DockPanel> 
     <DockPanel Grid.Column="1" Grid.Row="0"> 
      <igDP:XamDataGrid x:Name="ItemsSource" DataContext="{Binding Source={StaticResource dataContext}, Path=ItemsSource, Mode=TwoWay}" Grid.Row="0" Margin="10" AutoFit="true"> 
       <igDP:XamDataGrid.ViewSettings> 
        <igDP:GridViewSettings/> 
       </igDP:XamDataGrid.ViewSettings> 

       <igDP:XamDataGrid.FieldSettings> 
        <igDP:FieldSettings LabelTextAlignment="Left" AllowRecordFiltering="true" FilterOperandUIType="ExcelStyle" FilterStringComparisonType="CaseInsensitive" FilterOperatorDefaultValue="Contains" 
             LabelClickAction="SortByOneFieldOnlyTriState" SortComparisonType="Default"/> 
       </igDP:XamDataGrid.FieldSettings> 
       <igDP:XamDataGrid.FieldLayoutSettings> 
        <igDP:FieldLayoutSettings DataErrorDisplayMode="ErrorIconAndHighlight" SupportDataErrorInfo="RecordsAndCells" SelectionTypeRecord ="Single"         
           AutoGenerateFields="False" FilterUIType="FilterRecord"/> 
       </igDP:XamDataGrid.FieldLayoutSettings> 
       <igDP:XamDataGrid.FieldLayouts> 
        <igDP:FieldLayout> 
         <igDP:FieldLayout.Fields> 
          <igDP:Field Name="IsSelected" Label="Select" HorizontalContentAlignment="Left" Width="Auto" VerticalContentAlignment="Center"> 
           <igDP:Field.Settings> 
            <igDP:FieldSettings DataItemUpdateTrigger="OnCellValueChange"> 
             <igDP:FieldSettings.LabelPresenterStyle> 
              <Style TargetType="{x:Type igDP:LabelPresenter}"> 
               <Setter Property="ContentTemplate"> 
                <Setter.Value> 
                 <DataTemplate> 
                  <CheckBox Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked" Content="" /> 
                 </DataTemplate> 
                </Setter.Value> 
               </Setter> 
              </Style> 
             </igDP:FieldSettings.LabelPresenterStyle> 
            </igDP:FieldSettings> 
           </igDP:Field.Settings> 
          </igDP:Field> 
          <igDP:Field Label="Name" Name="Name" AllowEdit="False" HorizontalContentAlignment="Left" Width="Auto">        
          </igDP:Field> 
          <igDP:Field Label="Type" Name="Type" AllowEdit="False" HorizontalContentAlignment="Left" Width="*"/> 
          <igDP:Field Label="Background" Name="Background" AllowEdit="False" HorizontalContentAlignment="Left" Width="Auto"/> 
          <igDP:Field Label="Width" Name="Width" AllowEdit="False" HorizontalContentAlignment="Right" Width="Auto"/> 
          <igDP:Field Label="Height" Name="Height" AllowEdit="False" HorizontalContentAlignment="Right" Width="Auto"/>        
         </igDP:FieldLayout.Fields> 
        </igDP:FieldLayout> 
       </igDP:XamDataGrid.FieldLayouts> 
      </igDP:XamDataGrid> 
     </DockPanel> 
     <DockPanel Grid.Column="0" Grid.Row="1" Grid.RowSpan="2"> 
      <StackPanel Orientation="Vertical" DockPanel.Dock="Bottom">  
       <TextBox Text="Sample Text1"/> 
       <TextBox Text="Sample Text2"/>  
       <TextBox Text="Sample Text3"/> 
       <TextBox Text="Sample Text4"/>  
      </StackPanel> 
     </DockPanel> 
     <!--</StackPanel>--> 
    </Grid> 
</Window> 

的XAML代码隐藏页:

namespace UserInterface 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent();     
      //GraphicViewModel obj = new GraphicViewModel();     
      //ItemsSource.DataSource = obj.ItemsSource; 
     } 

     #region INotifyPropertyChanged Members 

     public event PropertyChangedEventHandler PropertyChanged; 

     private void NotifyPropertyChanged(string info) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(info)); 
      } 
     } 

     #endregion INotifyPropertyChanged Members 
     public GraphicViewModel GraphicViewModel 
     { 
      get { return this.DataContext as GraphicViewModel; } 
      set 
      { 
       this.DataContext = value; 
       if (this.DataContext != null) 
        NotifyPropertyChanged("GraphicViewModel"); 
      } 
     } 

     private void CheckBox_Checked(object sender, RoutedEventArgs e) 
     { 

     } 

     private void CheckBox_Unchecked(object sender, RoutedEventArgs e) 
     { 

     } 
    } 
} 

模型类:

namespace UserInterface.Model 
{ 
    public class GraphicsModel : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 
     protected virtual void NotifyOfPropertyChange(string property) 
     { 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs(property)); 
     } 

     private bool _isSelected; 
     public bool IsSelected 
     { 
      get { return _isSelected; } 
      set 
      { 
       if (_isSelected == value) return; 

       _isSelected = value; 
       NotifyOfPropertyChange("IsSelected"); 
      } 
     } 

     private string _name = string.Empty; 
     public string Name 
     { 
      get { return _name; } 
      set 
      { 
       if (_name != value) 
        _name = value; 
       NotifyOfPropertyChange("Name"); 
      } 
     } 

     private string _type = string.Empty; 
     public string Type 
     { 
      get { return _type; } 
      set 
      { 
       if (_type != value) 
        _type = value; 
       NotifyOfPropertyChange("Type"); 
      } 
     } 

     private string _width = string.Empty; 
     public string Width 
     { 
      get { return _width; } 
      set 
      { 
       if (_width != value) 
        _width = value; 
       NotifyOfPropertyChange("Width"); 
      } 
     } 

     private string _height = string.Empty; 
     public string Height 
     { 
      get { return _height; } 
      set 
      { 
       if (_height != value) 
        _height = value; 
       NotifyOfPropertyChange("Height"); 
      } 
     } 
    } 
} 

ViewModel类:

namespace UserInterface.ViewModel 
{ 
    public class GraphicViewModel : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 
     protected virtual void NotifyOfPropertyChange(string property) 
     { 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs(property)); 
     } 

     private ObservableCollection<GraphicsModel> _itemsSource = new ObservableCollection<GraphicsModel>(); 


     // MainWindow _view = null; 
     public ObservableCollection<GraphicsModel> ItemsSource 
     { 
      get { return _itemsSource; } 
      set 
      { 
       if (_itemsSource == value) return; 

       _itemsSource = value; 
       NotifyOfPropertyChange("ItemsSource"); 
      } 
     } 

     public GraphicViewModel() 
     { 
      //_view = view;   
      _itemsSource = new ObservableCollection<GraphicsModel>() { new GraphicsModel() { Name = "sdasdad", Type = "Model", IsSelected = false, Height = "1000", Width = "1370" } , 
      new GraphicsModel() { Name = "sdsa", Type = "Model", IsSelected = false, Height = "1000", Width = "1370" } ,new GraphicsModel() { Name = "sdasdad", Type = "Model", IsSelected = false, Height = "1000", Width = "1370" } ,new GraphicsModel() { Name = "asas", Type = "Model", IsSelected = false, Height = "1000", Width = "1370" } ,new GraphicsModel() { Name = "rewwe", Type = "Model", IsSelected = false, Height = "1000", Width = "1370" } ,};    
      //view.GraphicViewModel = this; 
     } 
    } 
} 
+1

观察:在你的'MainWindow'你不设置'GraphicViewModel'财产会设置DataContext。相反,你保持视图模型在资源部分,并通过StaticResource绑定到它..这是完全奇怪的。决定用哪种方式来使用它:要么通过代码将其设置为'window.DataContext',要么通过XAML将其设置为DataContext(都可以,大多都是相同的),或者,如果你想保留在资源中,然后适当地编写代码,并且根本不引用DataContext(它将保持为NULL) – quetzalcoatl

+0

并且关于(2)否,它不是。正常的'{Binding}'标记在XAML中与DI完全无关。 '{Binding}'只监视Source(或DataContext,如果没有指定Source),并观察该Source(DataContext)上的Path(property.property.property.xxx)。这很简单。根本不与DI容器交互。 – quetzalcoatl

+0

谢谢。我想直接在XAML中将DataContext设置为Xamdatagrid。我可以请求你粘贴工作/修改的代码,因为我也尝试过,但没有成功。我做错了什么。 – user3249586

当你写

<Window.Resources> 
    <dc:GraphicViewModel x:Key="dataContext"/> 
</Window.Resources> 

您是说“创造型GraphicViewModel的属性,并将其命名的DataContext”。这几乎是完全一样的,如代码隐藏在做这样的事情:

private GraphicViewModel dataContext = new GraphicViewModel(); 

当你写

<igDP:XamDataGrid DataContext="{Binding Source={StaticResource dataContext}, Path=ItemsSource, Mode=TwoWay}" .. /> 

你说的“igDP:XamDataGrid.DataContext属性绑定到dataContext.ItemsSource”。

现在对于为什么电网将无法装入,则.DataContext财产实际上并没有做任何事情。它只是控制之后的数据的持有者。所以,如果你写

<igDP:XamDataGrid ItemsSource="{Binding MyProperty}" /> 

这将是告诉WPF“设置XamDataGrid.ItemsSource属性等于XamDataGrid.DataContext.MyProperty”。

由于在上面的代码中设置DataContext等于dataContext.ItemsSource,它会尝试将值设置为dataContext.ItemsSource.MyProperty(当然这不存在)。

你真正需要的是像

<igDP:XamDataGrid ItemsSource="{Binding Source={StaticResource dataContext}, Path=ItemsSource}" .. /> 

这将网格绑定的.ItemsSource财产(这是它建立从数据行的属性)在<Window.Resources>名为“DataContext的”创建静态资源,并在该对象上的属性称为ItemsSource。这里虽然

第二个问题是你似乎有你的视图模型的多个副本在你的代码。就我个人而言,我建议不要像在您的GraphicViewModel中那样在XAML中创建对象。相反,我建议是这样的:

public MainWindow() 
{ 
    InitializeComponent();     
    this.DataContext = new GraphicViewModel(); 
} 

现在应该指出的是,这会在GraphicViewModel的新实例,但不会存储任何地方。如果你想在其他代码后面访问这个对象而不需要将this.DataContext改为GraphicViewModel,那么你应该在某处存储这个值。

一旦设置了Window.DataContext,您可以编写绑定而不指定绑定的自定义Source属性。

<igDP:XamDataGrid ItemsSource="{Binding ItemsSource}" .. /> 

这将工作,因为WPF控件默认查找DataContext,如果它没有专门设置。因此,在这种情况下,XamDataGrid的.DataContext属性为null,因此它将沿着可视化树向上查找带有DataContext的内容,直到它运行到您在构造函数中设置为您的GraphicViewModel的新实例的Window.DataContext

对于希望了解DataContext属性的人,我通常会将它们发送到this SO answer以避免必须始终重新输入相同的内容。如果你仍然在努力理解DataContext是什么或者它是如何使用的,我建议阅读它。

也就是说,依赖注入是不同的东西,根本不会在这里使用。

+0

感谢您的澄清。我从你的解释中了解到,试图做出这些改变,但网格仍然是空的。有一点要提到的是,XamDataGrid没有ItemsSource属性而非DataSource属性,所以我使用了它。我的更新代码如下:public MainWindow() { InitializeComponent(); ItemsSource.DataContext = new GraphicViewModel(); }并且, user3249586

+0

@ user3249586我建议下载一个像[WPF Snoop](https: //snoopwpf.codeplex.com/)并在运行时查看DataContext以确保它是正确的。这听起来可能不是 – Rachel

+0

小修正 - 打开单词“”创建一个类型GraphicViewModel的属性并将其命名为dataContext“ - 这完全不是真的,而且完全不同。你可能已经想过组件'x:Name'(它与你所写的类似的方式进行了松散地描述),但是把它写在Resource'x:Key'的上下文中(它把它放到'window.Resources [key ]'资源字典)。资源词典比共享,样式,主题和其他什么样的声音要复杂得多 - 尽管在这里,实际上,它们都不会完全看不到。 – quetzalcoatl

非常感谢@Rachel,@Daniel Filipov & @quetzalcoatl,现在我的代码工作了。在下面的文件所做的更改:

MainWindow.xaml.cs

public MainWindow() 
     { 
      InitializeComponent();   
      ItemsSource.DataContext= new GraphicViewModel(); 
     } 

MainWindow.xaml:

<igDP:XamDataGrid x:Name="ItemsSource" DataSource="{Binding ItemsSource, Mode=TwoWay}" .../>