gpt4 book ai didi

WPF DataGrid 与 RowDetailsTemplate 中的 DataGrid

转载 作者:行者123 更新时间:2023-12-03 10:37:51 35 4
gpt4 key购买 nike

我之前关于检测 VM 中的属性更改的帖子不够深入,所以我发布了这个

我有一个工作网格。每个工作可以有一个或多个员工。

DataGrid 的 RowDetailsTemplate 包含另一个用于显示员工的网格。因此,父网格绑定(bind)到作业列表。内部网格绑定(bind)到 Job 模型上的员工列表。

工作模式:

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>();
}
}

员工模型
public class Employee : _Base
{
private string _EmployeeName = string.Empty;
public string EmployeeName
{
get { return _EmployeeName; }
set
{
if (_EmployeeName != value)
{
_EmployeeName = value;
RaisePropertyChanged("EmployeeName");
}
}
}

private bool _IsChecked = false;
public bool IsChecked
{
get { return _IsChecked; }
set
{
if (_IsChecked != value)
{
_IsChecked = value;
RaisePropertyChanged("IsChecked");
}
}
}
}

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>

主窗口 View 模型
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;
}
}
}

我有一些问题:

1) 当我单击内部网格中的员工时,Job 模型上的 SelectedEmployee 属性不会触发。

2) MainWindowViewModel_PropertyChanged 在选择员工时不会触发。

3)注意内部网格下方的按钮。如何将其命令绑定(bind)到 MainWindowVM?

最佳答案

  • 正如你有 DataGrid inside DataGrid's row ,所以上面的 DataGrid 在某种程度上是 eating up the selectionchange for the inner DataGrid .要解决此问题,您需要强制更新子 DataGrid 的绑定(bind)源。为此,请捕获内部 DataGrid 的 SelectionChanged 事件,并在处理程序中执行以下操作。
     private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
    DataGrid grid = e.OriginalSource as DataGrid;
    var expression = grid.GetBindingExpression(DataGrid.SelectedItemProperty);
    expression.UpdateSource();

    }
  • MainwindowVM 没有任何 ischecked 属性,这就是为什么它的属性更改为该属性没有触发的原因。
  • 要解决这个问题,您需要做几件事。问题是 DataGrid 单元格和行不继承 DataContext 因为它们不在其可视树下。所以要解决这个问题,你必须使用 BindingProxy在 DataGrid
  • 的 rowdetails 中将 windows DataContext 带到您的按钮

    定义绑定(bind)代理类如下:
        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}}"/>

    关于WPF DataGrid 与 RowDetailsTemplate 中的 DataGrid,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18986848/

    35 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com