2017-06-09 52 views
0

我有一個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

回答

0

當你寫

<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

0

非常感謝@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}" .../> 
相關問題