【问题标题】:IsVisibleChanged is not triggered when TabItem visibility is programatically updated以编程方式更新 TabItem 可见性时不会触发 IsVisibleChanged
【发布时间】:2014-01-04 19:57:50
【问题描述】:

我有一个带有三个选项卡的选项卡控件,其中两个选项卡在程序启动时将“可见性”设置为折叠,在某些条件下变为可见,以后可以再次折叠。如果正在折叠的 TabItem 是当前选定的选项卡,则即使它已折叠,它的内容仍然可见。

选项卡的可见性绑定到我的 ViewModel,并以这种方式更新。

当任何选项卡的可见性发生变化时,我总是希望第一个选项卡被激活。我试图在后面编写一个简单的代码来处理这种情况,但唯一一次命中代码是在加载/卸载我的 UserControl 时。更新选项卡的可见性时永远不会调用处理程序。我尝试在 tabcontrol 及其项目上设置 IsVisibleChanged 属性,但我无法获得代码隐藏。

这是我的 xaml:

    <UserControl x:Class="MyNameSpace.MyControl"
        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" 
        IsVisibleChanged="TabControl_IsVisibleChanged>
<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/Platform.Presentation;component/Themes/MyTheme.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</UserControl.Resources>
<TabControl x:Name="_tabControl" IsVisibleChanged="TabControl_IsVisibleChanged">
    <TabItem Header="View 1" x:Name="_view1Tab" IsVisibleChanged="TabControl_IsVisibleChanged">
        <local:SingleWorkspaceView/>
    </TabItem>
    <TabItem Header="View 2" x:Name="_view2Tab" Visibility="{Binding TabVisibility}" IsVisibleChanged="TabControl_IsVisibleChanged">
        <local:WorkspaceDeploymentView/>
    </TabItem>
    <TabItem Header="View 3" x:Name="_view3Tab" Visibility="{Binding TabVisibility}" IsVisibleChanged="TabControl_IsVisibleChanged">
        <local:TabDeploymentView/>
    </TabItem>
</TabControl>

这是我的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;


namespace MyNameSpace
{                                               
/// <summary>
/// Interaction logic for TopLevelControl.xaml
/// </summary>
public partial class TopLevelControl : UserControl
{
        ApplicationViewModel _viewModel;
        public TopLevelControl()
        {
            _viewModel = new ApplicationViewModel();
            base.DataContext = _viewModel;
            InitializeComponent();
        }

        private void TabControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
           TabItem tab = sender as TabItem;
           if(tab != null && (bool)e.NewValue)
           {
              _tabControl.SelectedIndex = 0;
           }
        }
     }
 }

事件没有触发有什么原因吗?

【问题讨论】:

  • 每当 tabItem 的可见性发生变化时,事件处理程序都会为我命中。但是代替(bool)e.NewValue,您认为您不需要!(bool)e.NewValue吗?
  • 很奇怪。我删除了资源字典,并在视图加载时突然看到来自选项卡项的命中,但随后的可见性更改并没有导致处理程序运行。

标签: c# wpf xaml user-controls


【解决方案1】:

让我们以 MVVM 方式完成,无需任何代码隐藏

xaml 这里我们绑定了 TabControl 的 SelectedIndex="{Binding TabSelectedIndex}"

<TabControl SelectedIndex="{Binding TabSelectedIndex}">
        <TabItem Header="abc">
            <Button Content="ok"/>
        </TabItem>
        <TabItem Header="xyz" Visibility="{Binding TabVisibility}">
            <Button Content="ok"/>
        </TabItem>
        <TabItem Header="pqr" Visibility="{Binding TabVisibility}">
            <Button Content="ok"/>
        </TabItem>
    </TabControl>

xaml.cs

public MainWindow()
    {
        InitializeComponent();
        DataContext =new  ViewModel();
    }

视图模型

    public class ViewModel: INotifyPropertyChanged
{
    int tabSelectedIndex;
    //this will be bound to the SelectedIndex of Tabcontrol
    public int TabSelectedIndex
    {
        get { return tabSelectedIndex; }
        set { tabSelectedIndex = value;
            Notify("TabSelectedIndex"); 
        }
    }

    Visibility tabVisibility;
    //this will be binded to the Visibility of TabItem 
    public Visibility  TabVisibility
    {
        get { return tabVisibility; }
        set
        {
            tabVisibility = value;
            //this is the logic that will set firstTab selected when Visibility will be collapsed
        if (tabVisibility == Visibility.Collapsed)
        {
            tabSelectedIndex = 0;
            Notify("TabSelectedIndex");
        }
            Notify("TabVisibility"); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    void Notify(string propName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
}

我希望这会有所帮助。如果有帮助,那就说 MVVM Rocks :)

【讨论】:

  • 我非常感谢您的解决方案,但出于多种原因,我想避免为此制作视图模型:---与我正在尝试的解决方案 应该 i> 工作,并且代码行数会少得多。我很好奇为什么没有触发 IsVisibleChanged 属性。 ---我不介意在严格处理视图时使用代码隐藏,而不是对与模型有关的任何事情采取行动---与第一点相关,制作一个视图模型来处理这个是很多代码只是为了处理边缘情况:(
  • 我想你已经有 ViewModel 从你绑定可见性的地方
  • 我确实有一个用于整个应用程序的 ViewModel,它跟踪应用程序的状态。但是要使用 MVVM 解决这个问题,我必须为 TabItem 类创建另一个视图模型,就像@ethicallogics 在他的解决方案中所做的那样。
  • +1 我最终将其作为一种解决方法。我只是将 SelectedIndex 属性放在我现有的应用程序视图模型中。仍然不知道为什么这些事件没有触发。
猜你喜欢
  • 2019-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-09
  • 1970-01-01
相关资源
最近更新 更多