【问题标题】:Custom UserControl events自定义用户控件事件
【发布时间】:2015-02-27 00:56:52
【问题描述】:

我有一个UserControl,定义如下:

<UserControl x:Class="Speaker.View.Controls.Prompt"
         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:conv="clr-namespace:Speaker.View.Converters"
         mc:Ignorable="d" Height="Auto" Width="300" x:Name="PromptBox">
<UserControl.Resources>
    <conv:VisibilityConverter x:Key="VConverter" />
</UserControl.Resources>
<Border Background="White" Padding="10" BorderThickness="1" 
        BorderBrush="Gray" CornerRadius="10" Height="80" 
        Visibility="{Binding Path=Show, ElementName=PromptBox, 
                             Converter={StaticResource VConverter}}" 
        UseLayoutRounding="True">
    <Border.Effect>
        <DropShadowEffect BlurRadius="20" RenderingBias="Quality" />
    </Border.Effect>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="20" />
            <RowDefinition Height="10" />
            <RowDefinition Height="20" />
        </Grid.RowDefinitions>

        <TextBox x:Name="InputText" Width="Auto" Height="20" 
                 Text="{Binding Path=InfoText, ElementName=PromptBox, Mode=OneWay}"
                 Grid.Row="0" BorderThickness="0" Foreground="#FF8D8D8D" 
                 GotFocus="InputText_GotFocus" LostFocus="InputText_LostFocus" />
        <Separator Grid.Row="1" />
        <Button Content="{Binding Path=ButtonText, ElementName=PromptBox}" Grid.Row="2" 
                Width="100" Command="{Binding Path=OkCommand, ElementName=PromptBox}" />
    </Grid>
</Border>

我想做的是这样的:

当用户点击按钮时,我想运行一些代码(很明显:)) - 这个控件将用于其他一些控件/窗口,我想运行的代码会有所不同,具体取决于在一个场景上。那么如何将这个按钮的Command 属性与一些自定义命令绑定呢?示例用法:

<ctrls:Prompt Show="{Binding ShouldLogIn}" ButtonText="{Binding LogInText}"
              InfoText="{Binding LogInInfo}" OkCommand="what goes here???" Grid.Row="0" Grid.ZIndex="2" />

另外 - 我遵循 MVVM 模式,使用 MVVMLight fw,所以我希望解决方案也遵循它。

所以问题是 - 如何从提示控件之外绑定到 Button.Command?

【问题讨论】:

  • 这看起来不错,你不需要从 propmpt 绑定任何东西 Bind oneway: Button.Command
  • 但是如何从提示控件外部绑定到提示 Button.Command?
  • 我建议制作一个“自定义控件”而不是使用 UserControl。 IMO 它更适合您尝试做的事情。您可以从 TextBox 继承并为您想要的命令添加一些 DependecyProperties。你现在拥有的XAML,基本上可以作为控制模板使用。如果您真的想使用 UserControl,另一个选项是附加 DependecyProperty。

标签: c# wpf mvvm user-controls mvvm-light


【解决方案1】:

我还建议制作一个 CustomControl,但如果你想使用你的 UserControl,你需要在后面的代码中添加一个 DependencyProperty。

public partial class Prompt : UserControl
{
    private bool _canExecute;
    private EventHandler _canExecuteChanged;

    /// <summary>
    /// DependencyProperty for the OKCommand property.
    /// </summary>
    public static readonly DependencyProperty OKCommandProperty = DependencyProperty.Register("OKCommand", typeof(ICommand), typeof(Prompt), new PropertyMetadata(OnOKCommandChanged));

    /// <summary>
    /// Gets or sets the command to invoke when the OKButton is pressed.
    /// </summary>
    public ICommand OKCommand
    {
        get { return (ICommand)GetValue(OKCommandProperty); }
        set { SetValue(OKCommandProperty, value); }
    }

    /// <summary>
    /// Gets a value that becomes the return value of
    /// System.Windows.UIElement.IsEnabled in derived classes.
    /// </summary>
    protected override bool IsEnabledCore
    {
        get { return base.IsEnabledCore && _canExecute; }
    }

    // Command dependency property change callback. 
    private static void OnOKCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Prompt p = (Prompt)d;
        p.HookUpCommand((ICommand)e.OldValue, (ICommand)e.NewValue);
    }

    public Prompt()
    {
        InitializeComponent();
    }

    // Add the command. 
    private void AddCommand(ICommand command)
    {
        EventHandler handler = new EventHandler(CanExecuteChanged);
        _canExecuteChanged = handler;
        if (command != null)
            command.CanExecuteChanged += _canExecuteChanged;
    }

   private void CanExecuteChanged(object sender, EventArgs e)
    {
        if (OKCommand != null)
            _canExecute = OKCommand.CanExecute(null);

        CoerceValue(UIElement.IsEnabledProperty);
    }

    // Add a new command to the Command Property. 
    private void HookUpCommand(ICommand oldCommand, ICommand newCommand)
    {
        // If oldCommand is not null, then we need to remove the handlers. 
        if (oldCommand != null)
            RemoveCommand(oldCommand);

        AddCommand(newCommand);
    }

    // Remove an old command from the Command Property. 
    private void RemoveCommand(ICommand command)
    {
        EventHandler handler = CanExecuteChanged;
        command.CanExecuteChanged -= handler;
    }
}

【讨论】:

    猜你喜欢
    • 2011-01-12
    • 2013-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多