Silverlight MVVM - 按钮启用&可见性属性

时间:2011-05-06 20:13:34

标签: c# silverlight mvvm

所以我在MVVM应用程序&我开始把一些闪耀和放大抛光功能。

在我页面的左侧,我显示的是这些值:

DateActivated
DateCompleted
DateTrialClosed
DateAccountingClosed

如果DB中有日期,我会在文本块中显示它。如果没有,我正在向用户显示一个按钮,说“激活工作订单”,“完成工作订单”等...

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

我的下一步是在第一个之后禁用任何可见按钮(逻辑很简单......在单击按钮1之前无法单击按钮2。在1和2之前都不能单击按钮3点击)。我不确定实现这个的最佳方法是什么。作为一个FYI,我在我的项目中已经有一个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}" />

VM代码:

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

2 个答案:

答案 0 :(得分:2)

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

我认为执行此类操作的最佳方法是将可见性绑定到ViewModel中的属性。

您可以为每个变量使用转换器(这样您就可以在需要时返回Visibility.Collapsed或Visibility.Visible; - ))。

您可以对每个按钮使用“CanExecute”方法,因此在按下button1之前无法执行按钮2(例如,使用布尔变量)。您需要使用命令,因此与每个按钮关联的代码将位于ModelView中。

如果您需要示例,我可以在星期一将其粘贴到我的工作中: - )。

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

您的观点应该是这样的:

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

您可以搜索如何在MVVM中使用命令的示例,这里有simple example

对于转换器,如果您仍然喜欢隐藏和显示按钮,则应声明一个实现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}}" />

希望这对你有帮助; - )

答案 1 :(得分:1)

这里举了一个例子。

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

这些是命令:

        #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 string 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>