2013-09-24 81 views
1

我是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" /> 

回答

4

因此,根據我從一個項目中所學到的知識,我已經一勞永逸,我們有一個可行的模式。

假設你有一堆模態窗口,它們在應用程序中都被應用了相同的樣式。要在每個視圖上具有「保存」和「取消」按鈕,用於所有模式窗口的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的模板以Content屬性綁定的格式佈局指定ContentControls到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> 

用戶控件代碼:

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類型的依賴項屬性。那麼,或者你可以用RelativeSource的方式回到視覺樹上,像{Binding DataContext.SaveCommand, RelativeSource={RelativeSource AncestorType={x:Type MyView}}},但它有點髒。

相關問題