【问题标题】:How to handle enabled property of multiple tabs using Data Templates?如何使用数据模板处理多个选项卡的启用属性?
【发布时间】:2015-12-02 12:16:25
【问题描述】:

我有一个带有两个选项卡的窗口,其中包含两个不同的用户控件。为了启用/禁用到第二个选项卡的导航,我通过IPageViewModel 接口在两个VM 中实现了IsEnabled 属性。

当通过来自CustomerDetailsViewModel 的 Messenger 服务在 CustomerOrdersViewModel 中接收到 SelectedCustomer 时,IsEnabled 布尔属性设置为 true。

到目前为止,此方法有效,因为当我从第一个视图的数据网格中选择客户时,启用了第二个选项卡。但问题是当我尝试选择第一个选项卡以返回初始视图时,它被 禁用

这是具体导航issue的截屏。

我不知道为什么当我使用 Messenger 将 IsEnabled 属性设置为 true 时,两个选项卡都会启用。

有人对这里的问题有任何建议吗?

CustomerDetailsViewModel 中,我通过信使发送 selectedCustomer:

    private CustomerModel selectedCustomer;
    public CustomerModel SelectedCustomer
    {
        get
        {
            return selectedCustomer;
        }
        set
        {
            selectedCustomer = value;
            Messenger.Default.Send<CustomerModel>(selectedCustomer);
            RaisePropertyChanged("SelectedCustomer");
        }
    }

然后在 CustomerDetailsViewModel 中,IsEnabled 属性设置为 true,因为 SelectedCustomer 已被传递:

    public CustomerOrdersViewModel()
    {


        Messenger.Default.Register<CustomerModel>(this, OnCustomerReceived);


    }


    public void OnCustomerReceived(CustomerModel customer)
    {
        SelectedCustomer = customer;
        IsEnabled = true;
    }

这是包含两个用户控件以及为每个控件生成的选项卡的 ApplicationView xaml:

<Window x:Class="MongoDBApp.Views.ApplicationView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:views="clr-namespace:MongoDBApp.Views"
        xmlns:vm="clr-namespace:MongoDBApp.ViewModels"
        Title="ApplicationView"
        Width="800"
        Height="500">

    <Window.Resources>
        <DataTemplate DataType="{x:Type vm:CustomerDetailsViewModel}">
            <views:CustomerDetailsView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:CustomerOrdersViewModel}">
            <views:CustomerOrdersView />
        </DataTemplate>
    </Window.Resources>

    <Window.DataContext>
        <vm:ApplicationViewModel />
    </Window.DataContext>


    <TabControl ItemsSource="{Binding PageViewModels}"
                SelectedItem="{Binding CurrentPageViewModel}"
                TabStripPlacement="Top">
        <TabControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}" />
            </DataTemplate>
        </TabControl.ItemTemplate>
        <TabControl.ItemContainerStyle>
            <Style TargetType="{x:Type TabItem}">
                <Setter Property="IsEnabled" Value="{Binding IsEnabled}"/>
            </Style>
        </TabControl.ItemContainerStyle>
    </TabControl>
</Window>

【问题讨论】:

  • 为什么不将CustomerDetailsViewModelIsEnabled 属性默认为true?这是一个应该始终启用的选项卡,所以这对我来说最有意义。
  • 好的,IsEnabled 属性对于每个 VM 是独立的吗?那么这将是有道理的。
  • 是的,每个 IPageViewModel 都是每个选项卡的数据对象,因此它们可以有单独的 IsEnabled 值:)

标签: wpf mvvm tabcontrol boolean-logic itemcontainerstyle


【解决方案1】:

为什么不将CustomerDetailsViewModelIsEnabled 属性默认为true?

这是一个应该始终启用的选项卡,所以这对我来说最有意义。

【讨论】:

  • 我提出了一个关于将视图设置为在 MainWindow 上加载的问题,您对在我当前的设置中这样做有什么建议吗? stackoverflow.com/questions/34222224/…
  • @BrianJ 看起来你已经解决了,因为现在问题已被删除。这是我通常用于登录的代码的简化版本,如果您想知道的话:stackoverflow.com/a/9489180/302677 :)
【解决方案2】:

我假设您将新的 ViewModel(CustomerDetails 或 CustomerOrders)分配给 CurrentPageViewModel。每当您这样做时,都会创建一个新的类对象,默认情况下 IsEnabled 设置为 false。
解决方法是在与您的视图 (ApplicationViewModel) 关联的 ViewModel 中创建 IsEnabled 属性。然后在 ItemContrainerStyle 中引用如下:

 <Setter Property="IsEnabled" Value="{Binding RelativeSource={RelativeSource AncestoryType=Window}, Path=DataContext.IsEnabled}"/>

TabControlPages 的 ViewModel 中既不需要 IsEnabled 也不需要 Messages,因为您的 IsEnabled 属性驻留在主 ViewModel 中,并且两个 TabPage 都引用它。编辑
过了一会儿,我意识到默认情况下它会被禁用,因为 IsDefault 一开始就等于 false。这很复杂,因为您没有显式创建 TabPage。我为此附上了完整的解决方案,看看 here.

【讨论】:

  • 好的,如果我将 IsEnabled 属性移动到 ApplicationViewModel,如何根据在 CustomerDetails 中选择的客户将其设置为启用或禁用?我知道其余的不确定布尔值是如何设置的。
  • When a selection occures send new Message and in ApplicationViewModel's constructor register listening fo that message.它相当于你在注册/发送 CustomerModel 时所做的。
  • 好的,但我还需要在 CustomerDetailsVM 中注册监听,因为传入的 SelectedCustomer 用于该 VM 中的查询。我可以同时在 AppVM 和 CustomerDetailsVM 中注册,只需在 AppVM 中设置 IsEnabled 值吗?或者这是一个不好的方法..
  • 我更新了我的帖子,希望你会发现它有用。
  • 虽然该解决方案很好,但我接受了 Rachel 的回答,因为它在代码方面不太复杂。感谢您的意见,尽管在未来的开发中可能会派上用场。
猜你喜欢
  • 2017-04-22
  • 1970-01-01
  • 2022-07-11
  • 1970-01-01
  • 2017-06-17
  • 2013-07-05
  • 1970-01-01
  • 2013-03-21
  • 1970-01-01
相关资源
最近更新 更多