如何使用纯MVVM概念和依赖注入将WPF页面上不同集合的不同面板上可用的XamDataGrid绑定。
我有一个WPF XAML页面,有3个部分由DockPanels分隔。一个面板包含与集合绑定的INFRAGITICS XamDataGrid控件。如何使用纯MVVM概念和依赖注入将WPF页面上不同集合的不同面板上可用的XamDataGrid绑定。
- 我想以纯MVVM方式使用DataContext/DataSource属性绑定XamDataGrid控件。
- 此外,倒很理解,如果结合是通过依赖注入来完成。
我曾尝试不同的方法,但没有获得成功。我粘贴了以下代码以供参考。请帮助。
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;
}
}
}
当你写
<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是什么或者它是如何使用的,我建议阅读它。
也就是说,依赖注入是不同的东西,根本不会在这里使用。
感谢您的澄清。我从你的解释中了解到,试图做出这些改变,但网格仍然是空的。有一点要提到的是,XamDataGrid没有ItemsSource属性而非DataSource属性,所以我使用了它。我的更新代码如下:public MainWindow() { InitializeComponent(); ItemsSource.DataContext = new GraphicViewModel(); }并且,
@ user3249586我建议下载一个像[WPF Snoop](https: //snoopwpf.codeplex.com/)并在运行时查看DataContext以确保它是正确的。这听起来可能不是 – Rachel
小修正 - 打开单词“”创建一个类型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}" .../>
观察:在你的'MainWindow'你不设置'GraphicViewModel'财产会设置DataContext。相反,你保持视图模型在资源部分,并通过StaticResource绑定到它..这是完全奇怪的。决定用哪种方式来使用它:要么通过代码将其设置为'window.DataContext',要么通过XAML将其设置为DataContext(都可以,大多都是相同的),或者,如果你想保留在资源中,然后适当地编写代码,并且根本不引用DataContext(它将保持为NULL) – quetzalcoatl
并且关于(2)否,它不是。正常的'{Binding}'标记在XAML中与DI完全无关。 '{Binding}'只监视Source(或DataContext,如果没有指定Source),并观察该Source(DataContext)上的Path(property.property.property.xxx)。这很简单。根本不与DI容器交互。 – quetzalcoatl
谢谢。我想直接在XAML中将DataContext设置为Xamdatagrid。我可以请求你粘贴工作/修改的代码,因为我也尝试过,但没有成功。我做错了什么。 – user3249586