禁用一个绑定命令时锁定用户控件

时间:2017-08-21 21:22:10

标签: c# wpf user-controls caliburn.micro

在我的应用程序中,我有很多网格,所以我正在创建一个用户控件,其中包含我们将用于网格的所有可能按钮(添加,删除,插入,上移,下移等) 。我使用依赖项属性来设置按钮的可见性和状态(启用或禁用),并为点击事件使用路由事件。

我在我的项目中使用Caliburn.Micro,因此我使用Message.Attach指定多个事件及其附加的操作。就他们自己而言,这些工作没有问题。

我遇到的问题是当动作具有Can *属性时。例如,我有Add和Remove方法以及CanAdd和CanRemove属性来设置它们的状态。如果CanAdd或CanRemove为false(另一个为true),则两个按钮都被禁用(可能是整个用户控件被禁用)。

我可以通过使用不符合Caliburn.Micro命名状态的属性(例如CanAddRecord和CanRemoveRecord而不是CanAdd和CanRemove)来解决此问题,因此它不会自动使用它们然后在每个依赖项属性中设置绑定。我宁愿不这样做,但如果它只是唯一的方式。

我创建了一个简单的示例项目来展示这一点。该项目是在VS 2015中编写的,使用的是.NET 4.5.2。我正在使用Caliburn.Micro v3.1.0。

应用程序有一个主窗口,顶部有用户控件。用户控件具有“添加”和“删除”按钮。在用户控件下是一个显示计数的标签。 “添加”按钮增加计数,“删除”按钮减少计数。始终启用“添加”按钮。仅当计数大于0时才会启用“删除”按钮(因此您无法将计数设置为负数)。计数从1开始,因此两个按钮都启动。如果单击“添加”,则两个按钮都保持启用状如果单击“删除”直到计数变为0,则两个按钮最终都会被禁用。

这是设计原因,因为消息附加到用户控件而不是特定按钮?有办法解决这个问题吗?

我最初尝试将Message.Attach语句放在用户控件中,但是当单击按钮时,它似乎想要绑定到用户控件内部的Add和Remove方法。

的App.xaml

<Application
    x:Class="WpfApplication1.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1">

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary>
                    <local:AppBootstrapper x:Key="Bootstrapper" />
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

AppBootStrapper.cs

using System.Windows;
using Caliburn.Micro;

namespace WpfApplication1
{
    public class AppBootstrapper : BootstrapperBase
    {
        public AppBootstrapper()
        {
            Initialize();
        }

        protected override void OnStartup(object sender, StartupEventArgs e)
        {
            DisplayRootViewFor<MainViewModel>();
        }
    }
}

GridButtonBar.xaml

<UserControl
    x:Class="WpfApplication1.GridButtonBar"
    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="40" d:DesignWidth="230">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Button
            x:Name="AddButton"
            Content="Add"
            Grid.Column="0"
            Margin="3"
            IsEnabled="{Binding AddButtonIsEnabled}"
            Click="Add_OnClick" />

        <Button
            x:Name="RemoveButton"
            Content="Remove"
            Grid.Column="1"
            Margin="3"
            IsEnabled="{Binding RemoveButtonIsEnabled}"
            Click="Remove_OnClick" />
    </Grid>
</UserControl>

GridButtonBar.xaml.cs

using System.Windows;
using System.Windows.Controls;

namespace WpfApplication1
{
    public partial class GridButtonBar : UserControl
    {
        public static readonly DependencyProperty AddButtonIsEnabledProperty =
            DependencyProperty.Register(nameof(AddButtonIsEnabled), typeof(bool), typeof(GridButtonBar),
                new UIPropertyMetadata(true));

        public static readonly DependencyProperty RemoveButtonIsEnabledProperty =
            DependencyProperty.Register(nameof(RemoveButtonIsEnabled), typeof(bool), typeof(GridButtonBar),
                new UIPropertyMetadata(true));


        public static readonly RoutedEvent AddButtonClickedEvent = EventManager.RegisterRoutedEvent("AddButtonClicked",
            RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(GridButtonBar));

        public static readonly RoutedEvent RemoveButtonClickedEvent =
            EventManager.RegisterRoutedEvent("RemoveButtonClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler),
                typeof(GridButtonBar));


        public GridButtonBar()
        {
            InitializeComponent();
        }

        public bool AddButtonIsEnabled
        {
            get { return (bool) GetValue(AddButtonIsEnabledProperty); }
            set { SetValue(AddButtonIsEnabledProperty, value); }
        }

        public bool RemoveButtonIsEnabled
        {
            get { return (bool) GetValue(RemoveButtonIsEnabledProperty); }
            set { SetValue(RemoveButtonIsEnabledProperty, value); }
        }

        public event RoutedEventHandler AddButtonClicked
        {
            add { AddHandler(AddButtonClickedEvent, value); }
            remove { RemoveHandler(AddButtonClickedEvent, value); }
        }

        public event RoutedEventHandler RemoveButtonClicked
        {
            add { AddHandler(RemoveButtonClickedEvent, value); }
            remove { RemoveHandler(RemoveButtonClickedEvent, value); }
        }

        private void Add_OnClick(object sender, RoutedEventArgs e)
        {
            RaiseEvent(new RoutedEventArgs(AddButtonClickedEvent));
        }

        private void Remove_OnClick(object sender, RoutedEventArgs e)
        {
            RaiseEvent(new RoutedEventArgs(RemoveButtonClickedEvent));
        }
    }
}

MainView.xaml

<Window
    x:Class="WpfApplication1.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApplication1"
    xmlns:cal="http://www.caliburnproject.org"
    mc:Ignorable="d"
    Title="{Binding WindowTitle}"
    WindowStyle="SingleBorderWindow"
    ResizeMode="NoResize"
    Height="140" Width="250">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <local:GridButtonBar
            Grid.Row="0"
            cal:Message.Attach="[Event AddButtonClicked] = [Action Add];[Event RemoveButtonClicked] = [Action Remove]" />

        <Label
            Grid.Row="1"
            Margin="5"
            BorderBrush="Black"
            BorderThickness="1"
            HorizontalContentAlignment="Center"
            VerticalContentAlignment="Center"
            Content="{Binding Count}" />
    </Grid>
</Window>

MainViewModel.cs

using Caliburn.Micro;

namespace WpfApplication1
{
    public class MainViewModel : PropertyChangedBase
    {
        private const string WindowTitleDefault = "Caliburn Micro Test";
        private int _count = 1;
        private string _windowTitle = WindowTitleDefault;

        public string WindowTitle
        {
            get { return _windowTitle; }
            set
            {
                _windowTitle = value;
                NotifyOfPropertyChange(() => WindowTitle);
            }
        }

        public int Count
        {
            get { return _count; }
            set
            {
                _count = value;
                NotifyOfPropertyChange(() => Count);
            }
        }

        public bool CanAdd => true;

        public bool CanRemove => Count > 0;

        public void Add()
        {
            Count++;
        }

        public void Remove()
        {
            Count--;
            NotifyOfPropertyChange(() => CanRemove);
        }
    }
}

0 个答案:

没有答案
相关问题