2012-10-20 60 views
1

我試圖將我的ViewModel中的值綁定到自定義控件。 綁定似乎沒有工作。WPF + PRISM:綁定不適用於自定義控件

如果我添加一個常規的TextBlock並應用綁定,我會在TextBlock中的ViewModel中看到定義的值。

3個自定義文本框控件都沒有顯示來自我的ViewModel的值。 而且,當我點擊2個按鈕中的任意一個時,我無法到達ViewModel中的斷點。

AddAccountViewModel.xaml:

<UserControl 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:Controls="clr-namespace:Client.Infrastructure.Controls;assembly=Client.Infrastructure" 
     x:Class="Client.Modules.Accounts.Views.AddAccountView" 
     mc:Ignorable="d"> 
<Grid Width="400" Height="600"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="65"/> 
     <RowDefinition/> 
    </Grid.RowDefinitions> 
    <Controls:Header Title="New Account"/> 
    <StackPanel Grid.Row="1"> 
     <StackPanel Margin="25"> 
      <Controls:GTextBox Watermark="Title" TextBoxHeight="45" TextBoxWidth="350" FontSize="28" 
             Foreground="#999999" BorderBrush="#CCCCCC" Tip="e.g. Gmail, Dropbox, LastPass" 
             Text="{Binding Account.Title, Mode=TwoWay}"/> 

      <Controls:GTextBox Watermark="Account" TextBoxHeight="45" TextBoxWidth="350" FontSize="28" 
             Foreground="#999999" BorderBrush="#CCCCCC" Tip="e.g. [email protected]" Margin="0,25,0,0" 
             Text="{Binding Account.Name, Mode=TwoWay}"/> 

      <Controls:GTextBox Watermark="Key" TextBoxHeight="45" TextBoxWidth="350" FontSize="28" 
             Foreground="#999999" BorderBrush="#CCCCCC" Tip="e.g. random characters from the account provider" Margin="0,25,0,0" 
             Text="{Binding Account.Key, Mode=TwoWay}"/> 

      <Controls:SignedButton VerticalAlignment="Top" Width="275" Height="45" Foreground="#FFFFFF" 
            LeftSign="+" Text="Add an Account" TextSize="20" ButtonBackground="#3A5795" 
            HoverBackground="#C41AD7" HoverOpacity="1" Margin="0,50,0,0" Command="{Binding AddCommand}"/> 

      <Controls:SignedButton VerticalAlignment="Top" Width="275" Height="45" Foreground="#FFFFFF" 
            LeftSign="&lt;" Text="Back to Accounts" TextSize="20" ButtonBackground="#666666" 
            HoverBackground="#0FBDAC" HoverOpacity="1" Margin="0,25,0,0" 
            Command="{Binding NavigateToMainViewCommand}"/> 
     </StackPanel> 
    </StackPanel> 
</Grid> 
</UserControl> 

AddAccountView.xaml.cs:

public partial class AddAccountView : UserControl, IAddAccountView 
{ 
    public AddAccountView(IAddAccountViewModel accountViewModel) 
    { 
     InitializeComponent(); 

     ViewModel = accountViewModel; 
    } 

    public IViewModel ViewModel 
    { 
     get { return (IViewModel) DataContext; } 
     set { DataContext = value; } 
    } 
} 

AddAccountViewModel:

public class AddAccountViewModel : ViewModel, IAddAccountViewModel 
{ 
    private Account _account; 

    public AddAccountViewModel() 
    { 
     AddCommand = new DelegateCommand(Add, CanAdd); 
     NavigateToMainViewCommand = new DelegateCommand(Navigate, CanNavigate); 

     Account = new Account(Guid.NewGuid()) {Title = "Test", Name = "[email protected]", Key = "12345"}; 
    } 

    public Account Account 
    { 
     get { return _account; } 
     set 
     { 
      _account = value; 
      OnPropertyChanged("Account"); 
     } 
    } 

    public DelegateCommand AddCommand { get; private set; } 

    public DelegateCommand NavigateToMainViewCommand { get; private set; } 

    private void Add() 
    { 
     Account.Title = "Saved"; 
    } 

    private bool CanAdd() 
    { 
     return string.IsNullOrEmpty(Account.Error); 
    } 

    private bool CanNavigate() 
    { 
     return true; 
    } 

    private void Navigate() 
    { 
     int i = 0; 
    } 
} 

GTextBox.xaml:

<UserControl 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:Converters="clr-namespace:Client.Infrastructure.Converters" x:Class="Client.Infrastructure.Controls.GTextBox" 
     mc:Ignorable="d" 
     DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
<UserControl.Resources> 
    <Converters:CaseConverter x:Key="CaseConverter"/> 
</UserControl.Resources> 
<StackPanel> 
    <xctk:WatermarkTextBox FontFamily="{DynamicResource OpenSans}" Watermark="{Binding Watermark}" 
    Text="{Binding Text}" 
    Width="{Binding TextBoxWidth}" Height="{Binding TextBoxHeight}" 
    FontSize="{Binding FontSize}" Foreground="{Binding Foreground}" BorderBrush="{Binding BorderBrush}" Padding="10,3"> 
     <xctk:WatermarkTextBox.WatermarkTemplate> 
      <DataTemplate> 
       <ContentControl Content="{Binding Converter={StaticResource CaseConverter}, Mode=OneWay}"/> 
      </DataTemplate> 
     </xctk:WatermarkTextBox.WatermarkTemplate> 
    </xctk:WatermarkTextBox> 
    <TextBlock Text="{Binding Tip}" Foreground="#999999" FontSize="13" FontFamily="{DynamicResource OpenSans}" 
       TextOptions.TextFormattingMode="Display" Margin="10,5,0,0"/> 
</StackPanel> 
</UserControl> 

GTextBox.xaml.cs:

public partial class GTextBox : UserControl 
{ 
    public static DependencyProperty TextBoxHeightProperty = 
     DependencyProperty.Register("TextBoxHeight", typeof (double), typeof (GuardianTextBox)); 

    public static DependencyProperty TextBoxWidthProperty = 
     DependencyProperty.Register("TextBoxWidth", typeof (double), typeof (GuardianTextBox)); 

    public static DependencyProperty TextProperty = 
     DependencyProperty.Register("Text", typeof (string), typeof (GuardianTextBox)); 

    public static DependencyProperty TipProperty = 
     DependencyProperty.Register("Tip", typeof (string), typeof (GuardianTextBox)); 

    public static DependencyProperty WatermarkProperty = 
     DependencyProperty.Register("Watermark", typeof (string), typeof (GuardianTextBox)); 

    public GTextBox() 
    { 
     InitializeComponent(); 
    } 

    public string Text 
    { 
     get { return (string) GetValue(TextProperty); } 
     set { SetValue(TextProperty, value); } 
    } 

    public double TextBoxHeight 
    { 
     get { return (double) GetValue(TextBoxHeightProperty); } 
     set { SetValue(TextBoxHeightProperty, value); } 
    } 

    public double TextBoxWidth 
    { 
     get { return (double) GetValue(TextBoxWidthProperty); } 
     set { SetValue(TextBoxWidthProperty, value); } 
    } 

    public string Tip 
    { 
     get { return (string) GetValue(TipProperty); } 
     set { SetValue(TipProperty, value); } 
    } 

    public string Watermark 
    { 
     get { return (string) GetValue(WatermarkProperty); } 
     set { SetValue(WatermarkProperty, value); } 
    } 
} 

SignedButton.xaml:

<UserControl x:Class="Client.Infrastructure.Controls.SignedButton" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     mc:Ignorable="d" 
     d:DesignHeight="45" d:DesignWidth="245" 
     DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
<UserControl.Resources> 
    <Storyboard x:Key="OnMouseEnter"> 
     <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="grid"> 
      <EasingDoubleKeyFrame KeyTime="0" Value="1"/> 
      <EasingDoubleKeyFrame KeyTime="0:0:0.25" Value="{Binding HoverOpacity}"/> 
     </DoubleAnimationUsingKeyFrames> 
     <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="grid"> 
      <EasingColorKeyFrame KeyTime="0" Value="{Binding ButtonBackground}"/> 
      <EasingColorKeyFrame KeyTime="0:0:0.25" Value="{Binding HoverBackground}"/> 
     </ColorAnimationUsingKeyFrames> 
    </Storyboard> 
    <Storyboard x:Key="OnMouseLeave"> 
     <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="grid"> 
      <EasingDoubleKeyFrame KeyTime="0" Value="{Binding HoverOpacity}"/> 
      <EasingDoubleKeyFrame KeyTime="0:0:0.25" Value="1"/> 
     </DoubleAnimationUsingKeyFrames> 
     <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="grid"> 
      <EasingColorKeyFrame KeyTime="0" Value="{Binding HoverBackground}"/> 
      <EasingColorKeyFrame KeyTime="0:0:0.25" Value="{Binding ButtonBackground}"/> 
     </ColorAnimationUsingKeyFrames> 
    </Storyboard> 
</UserControl.Resources> 
<UserControl.Triggers> 
    <EventTrigger RoutedEvent="Mouse.MouseEnter"> 
     <BeginStoryboard Storyboard="{StaticResource OnMouseEnter}"/> 
    </EventTrigger> 
    <EventTrigger RoutedEvent="Mouse.MouseLeave"> 
     <BeginStoryboard Storyboard="{StaticResource OnMouseLeave}"/> 
    </EventTrigger> 
</UserControl.Triggers> 
<Grid x:Name="grid" Cursor="Hand" Background="{Binding ButtonBackground}"> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="50"/> 
     <ColumnDefinition Width="*"/> 
     <ColumnDefinition Width="50"/> 
    </Grid.ColumnDefinitions> 
    <TextBlock Text="{Binding LeftSign}" 
       FontFamily="{DynamicResource OpenSans}" FontSize="{Binding TextSize}" 
       HorizontalAlignment="Center" VerticalAlignment="Center" 
       TextOptions.TextFormattingMode="Display"/> 
    <TextBlock Text="{Binding Text}" 
       FontFamily="{DynamicResource OpenSans}" FontSize="{Binding TextSize}" 
       HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" 
       TextOptions.TextFormattingMode="Display"/> 
    <TextBlock Text="{Binding RightSign}" 
       FontFamily="{DynamicResource OpenSans}" FontSize="{Binding TextSize}" 
       HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="2" 
       TextOptions.TextFormattingMode="Display"/> 
</Grid> 
</UserControl> 

SignedButton.xaml.cs:

public partial class SignedButton : UserControl 
{ 
    public static DependencyProperty ButtonBackgroundProperty = 
     DependencyProperty.Register("ButtonBackground", typeof (string), typeof (SignedButton)); 

    public static DependencyProperty CommandParameterProperty = 
     DependencyProperty.Register("CommandParameter", typeof (object), typeof (SignedButton)); 

    public static DependencyProperty CommandProperty = 
     DependencyProperty.Register("Command", typeof (ICommand), typeof (SignedButton)); 

    public static DependencyProperty HoverBackgroundProperty = 
     DependencyProperty.Register("HoverBackground", typeof (string), typeof (SignedButton)); 

    public static DependencyProperty HoverOpacityProperty = 
     DependencyProperty.Register("HoverOpacity", typeof (double), typeof (SignedButton)); 

    public static DependencyProperty LeftSignProperty = 
     DependencyProperty.Register("LeftSign", typeof (string), typeof (SignedButton)); 

    public static DependencyProperty RightSignProperty = 
     DependencyProperty.Register("RightSign", typeof (string), typeof (SignedButton)); 

    public static DependencyProperty TextProperty = 
     DependencyProperty.Register("Text", typeof (string), typeof (SignedButton)); 

    public static DependencyProperty TextSizeProperty = 
     DependencyProperty.Register("TextSize", typeof (double), typeof (SignedButton)); 

    public SignedButton() 
    { 
     InitializeComponent(); 
     MouseUp += SignedButtonMouseUp; 
    } 

    public string ButtonBackground 
    { 
     get { return (string) GetValue(ButtonBackgroundProperty); } 
     set { SetValue(ButtonBackgroundProperty, value); } 
    } 

    public ICommand Command 
    { 
     get { return (ICommand) GetValue(CommandProperty); } 
     set { SetValue(CommandProperty, value); } 
    } 

    public object CommandParameter 
    { 
     get { return GetValue(CommandParameterProperty); } 
     set { SetValue(CommandParameterProperty, value); } 
    } 

    public string HoverBackground 
    { 
     get { return (string) GetValue(HoverBackgroundProperty); } 
     set { SetValue(HoverBackgroundProperty, value); } 
    } 

    public double HoverOpacity 
    { 
     get { return (double) GetValue(HoverOpacityProperty); } 
     set { SetValue(HoverOpacityProperty, value); } 
    } 

    public string LeftSign 
    { 
     get { return (string) GetValue(LeftSignProperty); } 
     set { SetValue(LeftSignProperty, value); } 
    } 

    public string RightSign 
    { 
     get { return (string) GetValue(RightSignProperty); } 
     set { SetValue(RightSignProperty, value); } 
    } 

    public string Text 
    { 
     get { return (string) GetValue(TextProperty); } 
     set { SetValue(TextProperty, value); } 
    } 

    public double TextSize 
    { 
     get { return (double) GetValue(TextSizeProperty); } 
     set { SetValue(TextSizeProperty, value); } 
    } 

    private void SignedButtonMouseUp(object sender, MouseButtonEventArgs e) 
    { 
     if (CommandParameter != null) Command.Execute(CommandParameter); 
    } 
} 

回答

0

這看起來像應該用自定義控件來完成,而不是用usercontrols。它不僅可以幫助您遵守MVVM模式,還可以讓您更好地控制一切。在知道如何去做之後,這並不是什麼大事。

順便說一句:試試MVVM-Light框架。它有一個RelayCommand<T>,你可能會喜歡:)