我有以下xaml视图:
<UserControl x:Class="MyViews.PersonView"
xmlns:views="clr-namespace:MyViews"
[...]
>
[...]
<dxb:BarManager x:Name="MainBarManager">
<dxb:BarManager.Items>
<dxb:BarButtonItem x:Name="bbiPrint"
Content="{Binding Print, Source={StaticResource CommonResources}}"
Command="{Binding PrintPersonsCommand}"
CommandParameter="{Binding PersonsCardView, ElementName=CardUserControl}"
/>
</dxb:BarManager.Items>
<Grid>
<Grid.RowDefinitions>
[...]
</Grid.RowDefinitions>
<views:CardView x:Name="CardUserControl" Grid.Row="2"/>
</Grid>
[...]
</UserControl>
CardView
的定义如下:
<UserControl x:Class="MyViews.CardView"
[...]>
[...]
<dxg:GridControl ItemsSource="{Binding Persons}" SelectedItems="{Binding SelectedPersons}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" SelectionMode="MultipleRow">
[...]
<dxg:GridControl.View>
<dxg:CardView x:Name="PersonsCardView"
[...]
CardTemplate="{StaticResource DisplayCardTemplate}"
PrintCardViewItemTemplate="{StaticResource PrintCardTemplate}"/>
</dxg:GridControl.View>
[...]
</dxg:GridControl>
</UserControl>
PrintPersonsCommand
在我的ViewModel中定义如下:
public class PersonViewModel
{
public PersonViewModel(...)
{
[...]
PrintPersonsCommand = new Prism.Commands.DelegateCommand<DataViewBase>(PrintPersons, CanPrintPersons);
}
public Prism.Commands.DelegateCommand<DataViewBase> PrintPersonsCommand { get; private set; }
private void PrintPersons(DataViewBase view)
{
_printService.ShowGridViewPrintPreview(view);
}
private bool CanPrintPersons(DataViewBase view)
{
return true;
}
}
现在,当我单击“打印”按钮时,上面的PrintPersons
方法总是带有null
。如何在上面的CardUserControl.PersonsCardView
xaml中传递MyViews.PersonView
,如何将PersonCardView
传递给命令?换句话说,我该如何解决
CommandParameter="{Binding PersonsCardView, ElementName=CardUserControl}"
使其起作用?
当前,我发现的唯一解决方案是将
替换为Command
和CommandParameter
ItemClick="OnPrintBtnClick"
,然后在PersonView
的代码隐藏文件中执行以下操作:
private void OnPrintBtnClick(object sender, ItemClickEventArgs e)
{
var ctxt = DataContext as PersonViewModel;
ctxt.PrintPersonsCommand.Execute(CardUserControl.PersonsCardView);
}
那行得通,但是我不敢相信没有其他办法。我对该解决方案不满意,因为我再也没有使用Command
的好处,例如自动评估Command的CanExecute
方法。我也可以将CardView
的xaml代码放在PersonView.xaml
中,但是我希望控件可以放在单独的文件中,因为我感觉它的结构更加合理,每个用户控件都有自己的职责,可以很好地完成任务被分割成单独的文件。而且,该解决方案过分紧密地将我的视图绑定到我的视图模型。
有人可以帮我吗?
答案 0 :(得分:2)
在不更改现有视图和视图模型层次结构的情况下,我能够使用 Tag 属性将GridControl.View传递给PersonViewModel。 您可以将CardView分配给CardView UserControl底部的Tag属性,然后以CommandParameter的身份访问此Tag。
CardView用户控件
<UserControl x:Class="MyViews.CardView"
[...]>
[...]
<dxg:GridControl ItemsSource="{Binding Persons}" SelectedItems="{Binding SelectedPersons}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" SelectionMode="MultipleRow">
[...]
<dxg:GridControl.View>
<dxg:CardView x:Name="PersonsCardView"
[...]
CardTemplate="{StaticResource DisplayCardTemplate}"
PrintCardViewItemTemplate="{StaticResource PrintCardTemplate}"/>
</dxg:GridControl.View>
[...]
</dxg:GridControl>
<UserControl.Tag>
<Binding ElementName="PersonsCardView"/>
</UserControl.Tag>
</UserControl>
打印按钮Xaml:
<dxb:BarButtonItem x:Name="bbiPrint"
Content="{Binding Print, Source={StaticResource CommonResources}}"
Command="{Binding PrintPersonsCommand}"
CommandParameter="{Binding ElementName=CardUserControl, Path=Tag}"
/>
答案 1 :(得分:0)
根据Insane的宝贵意见,我提出了以下两个更清洁的修复程序:
在PersonView
中,使用ItemClick
按钮上的Print
事件处理程序:
<dxb:BarButtonItem x:Name="bbiPrint"
Content="{Binding Print, Source={StaticResource CommonResources}}"
ItemClick="OnPrintBtnClick"/>
像这样修改相应的代码隐藏文件:
public partial class PersonView : UserControl
{
readonly IPrintService _printService;
public PersonView(IPrintService printService)
{
_printService = printService;
InitializeComponent();
}
private void OnPrintBtnClick(object sender, ItemClickEventArgs e)
{
_printService.ShowGridViewPrintPreview(CardUserControl.PersonsCardView);
}
}
因为在没有选择的情况下我想将“打印”按钮涂成灰色,所以我仍然需要添加一些代码来实现。我可以得到 1.将按钮代码更新为
<dxb:BarButtonItem x:Name="bbiPrint"
Content="{Binding Print, Source={StaticResource CommonResources}}"
ItemClick="OnPrintBtnClick" IsEnabled="{Binding CanPrintPersons}"/>
CanPrintPersons
中的PersonViewModel
属性就是这样。
在该解决方案中,我们有一个PersonView
及其底层PersonViewModel
和一个CardView
及其底层CardViewModel
。我不会详细描述该解决方案,因为在我的情况下这是过分的,但是为了完整起见,我将提出要点。单击Print
上的PersonView
按钮后,将调用PersonViewModel
的{{1}}。该命令向PrintCommand
发出Print
事件,该事件依次调用其自己的CardViewModel
。后一个命令调用
PrintCommand
其中_printService.ShowGridViewPrintPreview(View);
是View
的属性,该属性是在CardViewModel
加载时设置的,例如
CardView
因为我要打印两个子视图,所以我需要为每个视图添加一个视图模型。此外,这两个视图模型加上<dxmvvm:Interaction.Behaviors>
<dxmvvm:EventToCommand EventName="Loaded" Command="{Binding ViewLoadedCommand}" CommandParameter="{Binding ElementName=PersonsCardView}" />
</dxmvvm:Interaction.Behaviors>
需要访问要打印的人员列表。特别是,它们需要对相同数据的共享访问权,以便它们被同步。 here说明了一种简单的方法,并且完全可行。但是我认为,对于我拥有的简单用例而言,这不值得麻烦,因为它增加了不必要的复杂性。