繁体   English   中英

将命令绑定到模板化用户控件

[英]Binding command to a templated user control

我是WPF的新手,但由于有关该主题的好书,当然还有像这样的网站上的高质量帖子,因此能够在短时间内取得很多进展。 然而,现在我遇到了一些我似乎可以通过这些手段弄清楚的东西,所以我发布了我的第一个问题。

我在资源字典中有一个ControlTemplate,我将其应用于多个UserControl视图。 该模板提供了一个简单的叠加边框和两个按钮:保存和取消。 模板化用户控件包含各种文本框等,并根据上下文绑定到某些ViewModel。 我试图弄清楚当我在某些视图中使用/声明UserControl时如何将命令绑定到保存/取消按钮。 这是可能的,还是我做错了什么?

首先,模板:

<ControlTemplate x:Key="OverlayEditorDialog"
                 TargetType="ContentControl">
    <Grid>
        <Border HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch"
                Background="DarkGray"
                Opacity=".7"/>
        <Border HorizontalAlignment="Center" 
                VerticalAlignment="Center"
                Background="DarkGray">
                <Grid>
                   <RowDefinition Height="Auto"/>
                    <RowDefinition/>
                </Grid.RowDefinitions>                    
                <ContentPresenter Grid.Row="0"/>                    
                <Grid Grid.Row="1" 
                      Margin="10">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <Button Grid.Column="1"
                            Content="Cancel"
                            ***Command="{Binding CancelCommand}}"**
                            />
                    <Button Grid.Column="0"
                            Content="Save"
                            ***Command="{Binding Path=SaveCommand}"***/>
                </Grid>
            </Grid>
        </Border>
    </Grid>
</ControlTemplate>

该模板依次用于CustomerEditorOverlay用户控件

<UserControl x:Class="GarazhApp.View.CustomerEditorOverlay"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
<UserControl.Resources>
    <ResourceDictionary Source="Dictionary1.xaml"/>
</UserControl.Resources>
<ContentControl Template="{StaticResource ResourceKey=OverlayEditorDialog}">        
    <Grid Grid.Row="0"
          HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>                
        </Grid.RowDefinitions>
        <SomeElement/>
        <SomeOtherElement/>
    </Grid>
</ContentControl>    

...最后,用户控件被用作视图的一部分,如下所示:

<local:CustomerEditorOverlay Visibility="{Binding Path=CustomerViewModel.ViewMode, Converter={StaticResource myConverter}, FallbackValue=Collapsed}"
                                 d:IsHidden="True" />

所以,根据我从一个项目中学到的东西,我已经有了一个半年,我们有一个可行的模式。

假设你有一堆模态窗口,它们都在应用程序中应用了相同的样式。 要在每个视图上都有“保存”和“取消”按钮,用于所有模态窗口的UserControl具有多个依赖项属性。 此外,我们为您的命令指定虚拟方法(例如OnSaveCommand,OnCancelCommand,CanExecuteSaveCommand,CanExecuteCancelCommand),并将命令本身指定为视图继承的基本ViewModel中的属性。

最终,我们只需执行以下操作即可创建新的模态窗口:

<my:YourBaseView x:class="MyFirstView" xmlns:whatever="whatever" [...]>
    <my:YourBaseView.PrimaryButton>
         <Button Content="Save" Command="{Binding SaveCommand}" />
    </my:YourBaseView.PrimaryButton>

    <!-- some content -->
</my:YourBaseView>

附带代码隐藏:

public class MyFirstView : YourBaseView
{
    [Import] /* using MEF, but you can also do MvvmLight or whatever */
    public MyFirstViewModel ViewModel { /* based on datacontext */ }
}

和一个ViewModel:

public class MyFirstViewModel : ViewModelBase
{
    public override OnSaveCommand(object commandParameter)
    {
        /* do something on save */
    }
}

此UserControl的模板在网格布局中指定ContentControls,其Content属性绑定到PrimaryButton和SecondaryButton。 当然,模态的内容存储在UserControl的Content属性中,并且也显示在ContentPresenter中。

<Style TargetType="{x:Type my:YourBaseView}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type my:YourBaseView}">
                <Grid>
                    <!-- ignoring layout stuff -->
                    <ContentControl Content="{TemplateBinding Content}" />
                    <ContentControl Content="{TemplateBinding PrimaryButton}" />
                    <ContentControl Content="{TemplateBinding SecondaryButton}" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

UserControl代码:

public class YourBaseView : UserControl
{
    public static readonly DependencyProperty PrimaryButtonProperty =
        DependencyProperty.Register("PrimaryButton", typeof(Button), typeof(YourBaseView), new PropertyMetadata(null));
    public Button PrimaryButton
    {
        get { return (Button)GetValue(PrimaryButtonProperty); }
        set { SetValue(PrimaryButtonProperty, value); }
    }  

    /* and so on */
}

当然,您可以更改模板化视图的每个实例的样式。 我们碰巧坚持一种基本风格。

TL; DR编辑:我可能已经有点过分,因为我认为您只需要了解暴露每次创建新叠加层时通过XAML设置的Button类型的依赖属性。 那个,或者你可能会使用类似{Binding DataContext.SaveCommand, RelativeSource={RelativeSource AncestorType={x:Type MyView}}}的方式将你的方式返回到可视树中,但它有点脏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM