Silverlight MVVM - Button Enable & Visibility 属性



所以我在MVVM应用程序工作,我开始在功能上加一些光彩和润色。

在我的页面左侧,我显示以下值:

DateActivated
DateCompleted
DateTrialClosed
DateAccountingClosed

如果数据库中有日期,我会在文本块中显示它。如果没有,我将向用户显示一个按钮,说"激活工作订单"、"完成工作订单"等......

我将这 8 个(4 个文本块,4 个按钮)控件中的每一个的可见性绑定到我的 Windows.VisibilityViewModel中的唯一属性。在我的SelectedWorkOrder 中,我评估SelectedWorkOrder.DateActivated属性的当前值(例如)并相应地设置可见性属性。这对我来说有点冗长,但它按预期工作。

我的下一步是在第一个按钮之后禁用任何可见按钮(逻辑很简单......在单击按钮 1 之前,无法单击按钮 2。在同时单击按钮 1 和 2 之前,无法单击按钮 3)。我不确定实现这一点的最佳方法是什么。仅供参考,我的项目中已经有一个 boolToVisibility 值转换器......我只是不确定实现它与我现在所做的有什么不同(请参阅下面的 VM 代码)。

目前,我的 XAML 有这个:

<TextBlock Text="Proposed:" />
<TextBlock Text="Activated:" />
<TextBlock Text="Eng Completed:" />
<TextBlock Text="Trial Close:" />
<TextBlock Text="Accounting Close:" />
<TextBlock Text="{Binding SelectedWorkOrder.EstimatedStartDate}" Visibility="{Binding ProposedVisibility}" />
<TextBlock Text="{Binding SelectedWorkOrder.DateActivated}" Visibility="{Binding ActivatedTextBlockVisibility}" />
<Button Content="Activate Work Order" Visibility="{Binding ActivatedButtonVisibility}" />
<TextBlock Text="{Binding SelectedWorkOrder.DateCompleted}" Visibility="{Binding EngineeringCompletedTextBlockVisibility}" />
<Button Content="Work Order Eng Complete" Visibility="{Binding EngineeringCompletedButtonVisibility}" />
<TextBlock Text="{Binding SelectedWorkOrder.DateClosed}" Visibility="{Binding TrialCloseTextBlockVisibility}" />
<Button Content="Close Work Order (Trial)" Visibility="{Binding TrialCloseButtonVisibility}" />
<TextBlock Text="{Binding SelectedWorkOrder.DateClosed}" Visibility="{Binding AccountingCloseTextBlockVisibility}" />
<Button Content="Close Work Order (Actual)" Visibility="{Binding AccountingCloseButtonVisibility}" />

虚拟机代码:

if (_SelectedWorkOrder.DateActivated.ToShortDateString() != "1/1/0001")
{
    ActivatedTextBlockVisibility = Visibility.Visible;
    ActivatedButtonVisibility = Visibility.Collapsed;
}
else
{
    ActivatedTextBlockVisibility = Visibility.Collapsed;
    ActivatedButtonVisibility = Visibility.Visible;
}

(日期设置为1/1/0001在我的数据库访问层中,因为我正在实例化一个新DateTime,如果Is DBNull.Value = true

今晚我遇到了类似的问题:-)

我认为做这种事情的最好方法是将可见性绑定到 ViewModel 中的属性。

您可以对这些变量中的每一个使用转换器(因此您可以在预期时返回 Visibility.Collapsed 或 Visibility.Visible ;-))。

您可以对每个按钮使用"CanExecute"方法,以便在按下按钮 1 之前无法执行按钮 2(例如使用布尔变量)。您需要为此使用命令,以便与每个按钮关联的代码将位于模型视图中。

如果您需要示例,我可以在周一从我的工作中粘贴它们:-)。

直接在这里编码的小例子(我这里没有安装 silverlight)。

您的视图应该是这样的:

<Button Content="Activate Work Order" Command="{Binding ActivateWorkOrderCommand}" />

您可以搜索如何在 MVVM 中使用命令的示例,这里有一个简单的示例。

对于转换器,如果您仍然喜欢隐藏和显示按钮,则应声明一个实现 IValueConverter 的新类:

public class UniversalConverter : IValueConverter {
      public object Convert(object value, Type targetType, 
                         object parameter, CultureInfo culture) {
if(_SelectedWorkOrder.DateActivated.ToShortDateString() != "1/1/0001")
{
          return Visibility.Collapsed;
      }
else { return Visibility.Visible;
}

因此,您的视图也应该链接转换器:

<Button Content="Activate Work Order" Visibility="{Binding DateActivated, Converter={StaticResource DateConverter}}" />

希望这对你有帮助;-)

这里有一个小例子。

这是一个简单的示例,当您单击一个按钮时登录,当您单击另一个按钮时注销。

这些是命令:

        #region Login Command
        public ViewModelCommand LoginCommand { get; set; }
        public void Login(object parameter)
        {
            Code.Session.Session.Sesion.Logged = true;
        }
        public bool CanLogin(object parameter)
        {
            return !Code.Session.Session.Sesion.Logged;
        }
        #endregion

        #region Logout Command
        public ViewModelCommand LogoutCommand { get; set; }
        public void Logout(object parameter)
        {
            Code.Session.Session.Sesion.Logged = false;
        }
        public bool CanLogout(object parameter)
        {
            return Code.Session.Session.Sesion.Logged;
        }
        #endregion

若要绑定可见性和其他数据,请声明一个属性:

public const 字符串 SesionPropertyName = "Sesion";

private Model.Sesion _Sesion = Code.Session.Session.Sesion;
public Model.Sesion Sesion
{
    get
    {
        return _Sesion;
    }
    set
    {
        if (_Sesion == value)
        {
            return;
        }
        var oldValue = _Sesion;
        _Sesion = value;
        // Update bindings, no broadcast
        RaisePropertyChanged(SesionPropertyName);
    }
}
在这个例子中,我们需要在用户

登录时隐藏按钮,并在用户未登录时显示它,所以我做了这个转换器:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if ((bool)value)
            {
                return Visibility.Collapsed;
            }
            else
            {
                return Visibility.Visible;
            }
        }
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if ((Visibility)value == Visibility.Visible)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

最后,我们必须将其绑定到视图上,注意转换器:

<Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="221*" />
                <ColumnDefinition Width="140*" />
            </Grid.ColumnDefinitions>
            <Button Content="Logout" Grid.Column="1" HorizontalAlignment="Stretch" Margin="2" Name="bLogout" VerticalAlignment="Stretch" Command="{Binding LogoutCommand}" />
            <TextBlock Height="Auto" HorizontalAlignment="Stretch" Margin="2" Name="txtBlockUser" Text="{Binding Sesion.UserName}" VerticalAlignment="Center" TextWrapping="NoWrap" TextAlignment="Center" />
            <Grid Grid.ColumnSpan="2" >
                    <Button Content="Login" Command="{Binding LoginCommand}" Visibility="{Binding Sesion.Logged, Converter={StaticResource InverseBooleanVisibilityConverter}}"></Button>
            </Grid>
        </Grid>

最新更新