WPF-MVVM:从DataGrid样式内处理事件
我在WPF+MVVM的基础上开发了Prism+MEF应用程序,其中有许多数据网格,所以我构建了DataGridStyle以应用于所有模块中的所有数据网格。列标题中的样式添加过滤器文本框,当文本框文本更改如下时,我使用MVVM Light EventToCommand触发TextChanged事件:(此代码存在于DataGridStyle资源字典中) 以及包含栅格的视图:WPF-MVVM:从DataGrid样式内处理事件,wpf,mvvm,Wpf,Mvvm,我在WPF+MVVM的基础上开发了Prism+MEF应用程序,其中有许多数据网格,所以我构建了DataGridStyle以应用于所有模块中的所有数据网格。列标题中的样式添加过滤器文本框,当文本框文本更改如下时,我使用MVVM Light EventToCommand触发TextChanged事件:(此代码存在于DataGridStyle资源字典中) 以及包含栅格的视图: <DataGrid ItemsSource="{Binding Subsystems,Mode=TwoWay, Up
<DataGrid ItemsSource="{Binding Subsystems,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding Path=SelectedSubsystem, Mode=TwoWay}"
Name="SubsystemAllDataGrid"
Style="{StaticResource DataGridStyle}"
Grid.Row="2">
<DataGrid.Columns>
<DataGridTextColumn Header="Serial" Binding="{Binding Path=Serial, Mode=TwoWay}"></DataGridTextColumn>
<DataGridTextColumn Header="Type" Binding="{Binding Path=Type, Mode=TwoWay}"></DataGridTextColumn>
<DataGridTextColumn Header="System" Binding="{Binding Path=System, Mode=TwoWay}"></DataGridTextColumn>
<DataGridTextColumn Header="SubsystemNo" Binding="{Binding Path=SubsystemNo, Mode=TwoWay}"></DataGridTextColumn>
<DataGridTextColumn Header="Description" Binding="{Binding Path=Description, Mode=TwoWay}"></DataGridTextColumn>
<DataGridTextColumn Header="Scope" Binding="{Binding Path=Scope, Mode=TwoWay}"></DataGridTextColumn>
<DataGridTextColumn Header="Area" Binding="{Binding Path=Area, Mode=TwoWay}"></DataGridTextColumn>
<DataGridTextColumn Header="Priority" Binding="{Binding Path=Priority, Mode=TwoWay}"></DataGridTextColumn>
<DataGridTextColumn Header="DossierLocation" Binding="{Binding Path=DossierLocation, Mode=TwoWay}"></DataGridTextColumn>
<DataGridTextColumn Header="Parts" Binding="{Binding Path=Parts, Mode=TwoWay}"></DataGridTextColumn>
<DataGridTextColumn Header="Status" Binding="{Binding Path=Status, Mode=TwoWay}"></DataGridTextColumn>
<DataGridTextColumn Header="StatusDate" Binding="{Binding Path=StatusDate, Mode=TwoWay}"></DataGridTextColumn>
<DataGridTextColumn Header="MCDate" Binding="{Binding Path=MCDate, Mode=TwoWay}"></DataGridTextColumn>
<DataGridTextColumn Header="PlnMCDate" Binding="{Binding Path=PlnMCDate, Mode=TwoWay}"></DataGridTextColumn>
<DataGridTextColumn Header="Remark" Binding="{Binding Path=Remark, Mode=TwoWay}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
问题是:
当我在数据网格的一列标题的文本框中输入过滤文本时,不会发生任何情况,并且以下点的断点未命中:
1-GetTextChangedCommand和SetTextChangedCommand
2-CommandChanged()方法
我是wpf新手,所以我确信wpf或C#code…(代码)中存在错误,所以请帮助我修复这些错误
注意:我不使用代码隐藏
提前感谢看起来您的命令绑定不起作用。请尝试以下操作:
Command="{Binding Path=TextChangedCommand}"
或
断点未命中使我遇到绑定问题 需要将命令的datacontext设置为定义命令的位置。因此,如果在viewmodel中定义了命令,则需要使用以下命令,但需要将ansestor类型设置为绑定到viewmodel的对象类型。这通常是您的视图,而不是datagrid:
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ViewType}} Path=DataContext.TextChangedCommand}"
因此,如果视图是窗口或用户控件,则将ViewType更改为相应的类型
运行应用程序时,您还可以在输出窗口中查看是否为命令生成了任何绑定错误
编辑1:
不要使用dependency属性,请在视图模型中使用MVVM Light中的中继命令:
this.YourRelayCommand = new RelayCommand( ExecuteYourCommand, CanYourCommandExecute);
public RelayCommand YourRelayCommand{ get; private set; }
public bool CanYourCommandExecute() {
}
public void ExecuteYourCommand() {
//TODO: Do code here
}
我应用了这两个选项,但当我在任何列标题的“过滤器”文本框中输入过滤器文本时,仍然没有任何结果。为什么不将文本框的文本属性绑定到ViewModel中的属性。所以你可以在这个属性的setter中调用TextChangedCommand。我尝试过这样做,但我有两个问题,第一个问题:getter被调用,但setter从未调用过我不知道为什么。第二个问题:我需要使用EventToCommand将事件参数传递给视图模型。这似乎是MVVM light特有的问题。@J King:当我在“过滤器”文本框中输入文本时,仍然没有发生任何事情。顺便说一句,我在附加的属性RegisterAttached语句中插入了一个断点,该语句在视图打开时被命中。您能在定义视图和datagrid的地方发布整个xaml吗。您的输出窗口中有任何绑定错误吗?另外,如果您使用的是MVVM Light,为什么不使用为此目的而设计的中继命令?@J King:my view的整个xaml分为3部分。第一部分包含用于添加行、删除行的按钮。。。etc以及我在问题中包含的网格的第二部分和第三部分是页脚。@J King:DataContext是在视图的代码隐藏中设置的,因为我使用MEF(Microsoft Extensibility Framework),并且在输出窗口中没有绑定错误。我必须使用MVVM Light,使我能够从DataGrid样式中触发事件,而不必使用代码隐藏。
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}} Path=DataContext.TextChangedCommand}"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ViewType}} Path=DataContext.TextChangedCommand}"
this.YourRelayCommand = new RelayCommand( ExecuteYourCommand, CanYourCommandExecute);
public RelayCommand YourRelayCommand{ get; private set; }
public bool CanYourCommandExecute() {
}
public void ExecuteYourCommand() {
//TODO: Do code here
}