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

发布于 2024-11-05 09:42:21 字数 2395 浏览 1 评论 0原文

所以我正在研究 MVVM 应用程序和应用程序。我开始添加一些光泽和颜色。完善功能。

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

DateActivated
DateCompleted
DateTrialClosed
DateAccountingClosed

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

我正在绑定这 8 个(4 个文本块,4 个按钮)控件中每个控件的可见性到我的 ViewModelWindows.Visibility 类型的唯一属性。在 SelectedWorkOrder 的 setter 中,我评估 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}" />

VM 代码:(

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

当我实例化一个新的 DateTime 时,日期在我的数据库访问层中设置为 1/1/0001 DBNull.Value = true

So I'm working in MVVM application & I'm starting to put some of the shine & polish on the functionality.

On the left side of my page, I am displaying these values:

DateActivated
DateCompleted
DateTrialClosed
DateAccountingClosed

If there's a date in the DB, I'm displaying it in a textblock. If there's not, I'm displaying a button to the user, saying "Activate Work Order", "Complete Work Order", etc...

I'm binding the visibility of each of these 8 (4 textblock, 4 button) controls to a unique property in my ViewModel of type Windows.Visibility. In my setter of the SelectedWorkOrder, I evaluate the current value of the SelectedWorkOrder.DateActivated property (for example) and set the visibility properties accordingly. This is slightly verbose for me, but it's working as expected.

My next step is to disable any visible buttons after the first one (logic is simple... can't click button 2 until button 1 has been clicked. Can't click button 3 until both 1 & 2 have been clicked). I'm not sure what the best way to implement this is. As an FYI on this, I have a boolToVisibility value converter already in my project... I'm just not sure that implementing it would be any different than I am doing now (see VM code below).

Currently I have this for my 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 Code:

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

(The date is set to 1/1/0001 in my database access layer as I'm instantiating a new DateTime if Is DBNull.Value = true)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

听风吹 2024-11-12 09:42:21

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

我认为做这类事情的最佳方法是将可见性绑定到 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}}" />

希望这对您有帮助;-)

I had a similar problem this evening :-)

I think the best way to do this kind of stuff is binding visibility to a property in the ViewModel.

You can use a converter for each of these variables (so you can return a Visibility.Collapsed or a Visibility.Visible when expected ;-)).

You can use the "CanExecute" method for each of these buttons so the button 2 is not able to be executed until button1 is pressed (with a boolean variable for example). You hace to use commands for this so the code associated to each button will be in the ModelView.

If you need examples I can paste them from my job on monday :-).

A little example by coding it here directly (I don't have silverlight installed here).

Your view should be like this:

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

You can search examples of how to use Commands in MVVM, here you have a simple example.

For the converters, if you still prefer to hide and show the buttons, you should declare a new Class that implements 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;
}

So your view should link the converter too:

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

Hope this help you ;-)

灰色世界里的红玫瑰 2024-11-12 09:42:21

这是一个小例子。

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

这些是命令:

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

Here goes a little example.

It's a simple example to login when you click one button and logout when you click in another.

These are the commands:

        #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

To bind the visibility and other data, declare a property:

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);
    }
}

In this example, we need to hide button when user is logged and show it when user is not, so I made this converter:

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;
            }
        }

Finally, we have to bind it to the view, pay attention to the converter:

<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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文