1

我正在尝试将 my 中的值绑定ViewModel到自定义控件。绑定似乎不起作用。

如果我添加一个常规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. user@example.com" 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; }
    }
}

添加帐户视图模型:

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 = "test@test.com", 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); }
    }
}

签名按钮.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>

签名按钮.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);
    }
}
4

1 回答 1

0

这看起来应该使用自定义控件而不是用户控件来完成。它不仅可以帮助您遵守 MVVM 模式,还可以让您更好地控制一切。在你知道怎么做之后,这并不是什么大事。

顺便说一句:尝试 MVVM-Light 框架。它有一个RelayCommand<T>你可能喜欢的:)

于 2012-10-21T10:10:49.223 回答