WPF DataGrid,其中DataGrid位于RowDetailsTemplate中
我上一篇关于检测虚拟机中的属性更改的文章不够深入,所以我发布了这篇文章 我有很多工作。每个工作可以有一个或多个员工 DataGrid的RowDetailsTemplate包含另一个显示员工的网格。所以到父网格绑定到一个作业列表。内部网格绑定到工作模型中的员工列表 工作模式:WPF DataGrid,其中DataGrid位于RowDetailsTemplate中,wpf,mvvm,datagrid,Wpf,Mvvm,Datagrid,我上一篇关于检测虚拟机中的属性更改的文章不够深入,所以我发布了这篇文章 我有很多工作。每个工作可以有一个或多个员工 DataGrid的RowDetailsTemplate包含另一个显示员工的网格。所以到父网格绑定到一个作业列表。内部网格绑定到工作模型中的员工列表 工作模式: public class Job : _Base { private string _JobName = string.Empty; public string JobName { g
public class Job : _Base
{
private string _JobName = string.Empty;
public string JobName
{
get { return _JobName; }
set
{
if (_JobName != value)
{
_JobName = value;
RaisePropertyChanged("JobName");
}
}
}
private string _JobNumber = string.Empty;
public string JobNumber
{
get { return _JobNumber; }
set
{
if (_JobNumber != value)
{
_JobNumber = value;
RaisePropertyChanged("JobNumber");
}
}
}
private ObservableCollection<Employee> _Employees;
public ObservableCollection<Employee> Employees
{
get { return _Employees; }
set
{
if (_Employees != value)
{
if (_Employees != value)
{
_Employees = value;
RaisePropertyChanged("Employees");
}
}
}
}
private Employee _SelectedEmployee;
public Employee SelectedEmployee
{
get { return _SelectedEmployee; }
set
{
if (_SelectedEmployee != value)
{
if (_SelectedEmployee != value)
{
_SelectedEmployee = value;
RaisePropertyChanged("SelectedEmployee");
}
}
}
}
public Job()
{
Employees = new ObservableCollection<Employee>();
}
}
XAML
<DataGrid ItemsSource="{Binding Jobs}"
SelectedItem="{Binding SelectedJob}"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Job Name" Binding="{Binding JobName}" />
<DataGridTextColumn Header="Job Number" Binding="{Binding JobNumber}" />
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<DataGrid ItemsSource="{Binding Employees}"
SelectedItem="{Binding SelectedEmployee}"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding IsChecked}"/>
<DataGridTextColumn Binding="{Binding EmployeeName}"/>
</DataGrid.Columns>
</DataGrid>
<Button Margin="5"
Height="23"
Width="75"
HorizontalAlignment="Left"
Content="Remove"/>
</StackPanel>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
主窗口视图模型
public class MainWindowViewModel : _Base
{
private ObservableCollection<Job> _Jobs;
public ObservableCollection<Job> Jobs
{
get { return _Jobs; }
set
{
if (_Jobs != value)
{
if (_Jobs != value)
{
_Jobs = value;
RaisePropertyChanged("Jobs");
}
}
}
}
private Job _SelectedJob;
public Job SelectedJob
{
get { return _SelectedJob; }
set
{
if (_SelectedJob != value)
{
if (_SelectedJob != value)
{
_SelectedJob = value;
RaisePropertyChanged("SelectedJob");
}
}
}
}
public MainWindowViewModel()
{
this.PropertyChanged += new PropertyChangedEventHandler(MainWindowViewModel_PropertyChanged);
}
void MainWindowViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName.Trim().ToLower() == "ischecked")
{
int x = 1;
}
}
}
public类MainWindowViewModel:\u Base
{
私人可观察收集工作;
公开收集工作
{
获取{return_Jobs;}
设置
{
如果(_Jobs!=值)
{
如果(_Jobs!=值)
{
_工作=价值;
RaiseProperty变更(“工作”);
}
}
}
}
私人工作(u selected Job);;
公共职务选定职务
{
获取{return\u SelectedJob;}
设置
{
如果(_SelectedJob!=值)
{
如果(_SelectedJob!=值)
{
_SelectedJob=值;
RaisePropertyChanged(“SelectedJob”);
}
}
}
}
公共主窗口视图模型()
{
this.PropertyChanged+=新的PropertyChangedEventHandler(MainWindowViewModel\u PropertyChanged);
}
void MainWindowViewModel\u属性已更改(对象发送方,System.ComponentModel.PropertyChangedEventArgs e)
{
如果(e.PropertyName.Trim().ToLower()=“ischecked”)
{
int x=1;
}
}
}
我有几个问题:
1) 在内部网格中单击员工时,不会激发职务模型上的SelectedEmployee属性
2) 选中员工时,不会激发MainWindowViewModel_属性Changed
3) 请注意内部网格下面的按钮。如何将其命令绑定到MainWindowVM
,因此上面的DataGrid在某种程度上消耗了内部DataGrid的selectionchange
。要解决这个问题,您需要强制更新子DataGrid的绑定源。为此,请捕获内部DataGrid的SelectionChanged事件,并在处理程序中执行以下操作
private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
DataGrid grid = e.OriginalSource as DataGrid;
var expression = grid.GetBindingExpression(DataGrid.SelectedItemProperty);
expression.UpdateSource();
}
BindingProxy
将windows DataContext带到DataGrid的rowdetails中的按钮 public class MyBindingProxy : Freezable
{
public static readonly DependencyProperty BindingDataProperty =
DependencyProperty.Register("BindingData", typeof(object),
typeof(MyBindingProxy), new UIPropertyMetadata(null));
protected override Freezable CreateInstanceCore()
{
return new MyBindingProxy();
}
public object BindingData
{
get { return (object)GetValue(BindingDataProperty); }
set { SetValue(BindingDataProperty, value); }
}
}
现在,在窗口的资源(DataGrid所在的位置)中创建代理实例,并将BindingData设置为窗口的DataContext,即MainWindowViewModel,如下所示:
<Window.Resources>
<local:MyBindingProxy x:Key="myproxy" BindingData="{Binding}" />
</Window.Resources>
现在只需在按钮上设置如下命令:
<Button Margin="5"
Height="23"
Width="75"
HorizontalAlignment="Left"
Content="Remove"
Command="{Binding BindingData.MyCommand, Source={StaticResource myproxy}}"/>
,因此上面的DataGrid在某种程度上消耗了内部DataGrid的selectionchange
。要解决这个问题,您需要强制更新子DataGrid的绑定源。为此,请捕获内部DataGrid的SelectionChanged事件,并在处理程序中执行以下操作
private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
DataGrid grid = e.OriginalSource as DataGrid;
var expression = grid.GetBindingExpression(DataGrid.SelectedItemProperty);
expression.UpdateSource();
}
BindingProxy
将windows DataContext带到DataGrid的rowdetails中的按钮 public class MyBindingProxy : Freezable
{
public static readonly DependencyProperty BindingDataProperty =
DependencyProperty.Register("BindingData", typeof(object),
typeof(MyBindingProxy), new UIPropertyMetadata(null));
protected override Freezable CreateInstanceCore()
{
return new MyBindingProxy();
}
public object BindingData
{
get { return (object)GetValue(BindingDataProperty); }
set { SetValue(BindingDataProperty, value); }
}
}
现在,在窗口的资源(DataGrid所在的位置)中创建代理实例,并将BindingData设置为窗口的DataContext,即MainWindowViewModel,如下所示:
<Window.Resources>
<local:MyBindingProxy x:Key="myproxy" BindingData="{Binding}" />
</Window.Resources>
现在只需在按钮上设置如下命令:
<Button Margin="5"
Height="23"
Width="75"
HorizontalAlignment="Left"
Content="Remove"
Command="{Binding BindingData.MyCommand, Source={StaticResource myproxy}}"/>
选择这些对象的目的是什么?我会认真地重新考虑将名为isChecked
的属性放在Employee
内,或SelectedEmployee
放在Job
内。这些表示视图的状态,这将视图逻辑与模型域相耦合。用户可以选中/取消选中任意数量的员工,然后单击“删除”。这就是目的这些选定对象的目的是什么?我会认真地重新考虑将名为isChecked
的属性放在Employee
内,或SelectedEmployee
放在Job
内。这些表示视图的状态,这将视图逻辑与模型域相耦合。用户可以选中/取消选中任意数量的员工,然后单击“删除”。这就是为什么自从你发布后我一直在看这个,我很抱歉,但这一切看起来像是一个黑客。我不敢相信一个简单的一对多网格设置需要所有这些。另外,你说的是与事件挂钩。这不是真正的MVVM。在没有事件的情况下绑定应该是可能的。自从你发布后,我一直在看这个,我很抱歉,但这一切看起来像是一个黑客。我不敢相信一个简单的一对多网格设置需要所有这些。另外,你说的是与事件挂钩。这不是真正的MVVM。绑定应该可以在没有事件的情况下进行。