带有TabControl的Silverlight 3应用程序使用IValueConverter绑定到ObservableCollection.应用程序启动时初始绑定工作(转换器调用).对绑定集合的更改,Clear()或Add()不会反映在未调用的TabControl ...转换器中.
注意:绑定的ListBox反映了对绑定集合的更改,而TabControl则没有.
想法?
/ JHD
XAML绑定......
<UserControl.Resources>
<local:ViewModel x:Key="TheViewModel"/>
<local:TabConverter x:Key="TabConverter" />
</UserControl.Resources>
<StackPanel DataContext="{StaticResource TheViewModel}">
<ListBox ItemsSource="{Binding Classnames}" />
<controls:TabControl x:Name="TheTabControl"
ItemsSource="{Binding Classnames, Converter={StaticResource TabConverter}, ConverterParameter=SomeParameter}"/>
<Button Click="Button_Click" Content="Change ObservableCollection" />
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
ViewModel ......
namespace DatabindingSpike
{
public class ViewModel
{
private ObservableCollection<string> _classnames = new ObservableCollection<string>();
public ViewModel()
{
_classnames.Add("default 1 of 2");
_classnames.Add("default 2 of 2");
}
public ObservableCollection<string> Classnames
{
get { return _classnames; }
set { _classnames = value; }
}
}
} …Run Code Online (Sandbox Code Playgroud) 在 Windows 窗体中,TabControl 的默认行为是,如果选项卡占用太多空间 (MultiLine = false),则将选项卡溢出到可滚动区域。
在 WPF 中实现此行为的最佳方法是什么?
更新
我试图找到一个解决方案TabControl.ItemsPanel,但似乎我放在那里的任何东西都被完全忽略了,所以出于这个原因,我走了一条艰难的路,并从TabControl.Template令人难以置信的开始,如果事实证明我们必须这样做才是正确的做法。
远未完成,我对问题的起始解决方案如下。
<TabControl>
<TabControl.Template>
<ControlTemplate TargetType="{x:Type TabControl}">
<DockPanel>
<ScrollViewer DockPanel.Dock="Top"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Disabled">
<StackPanel Orientation="Horizontal" IsItemsHost="True" />
</ScrollViewer>
<ContentPresenter ContentSource="SelectedContent" />
</DockPanel>
</ControlTemplate>
</TabControl.Template>
<TabItem Header="One">First</TabItem>
<TabItem Header="Two">Second</TabItem>
<TabItem Header="Three">Third</TabItem>
<TabItem Header="Four">Fourth</TabItem>
<TabItem Header="Five">Fifth</TabItem>
</TabControl>
Run Code Online (Sandbox Code Playgroud) 如果将控件放入 DataTemplate 中,为什么它们的各个状态会复制或反映在 TabControl 中的每个选项卡中?你在一个选项卡中更改它,所有其他选项卡都会反映,这是为什么?!在我看来,TabControl 仅初始化一个模板化的 ContentControl,并且每次单击选项卡都会重新复制其中的整个内容 - 使旧的控件状态保持不变。要明白我的意思,请考虑将其放入您的 XAML-Pad 中:
<TabControl>
<TabControl.ContentTemplate>
<DataTemplate>
<Border>
<TextBox Text="test"/>
</Border>
</DataTemplate>
</TabControl.ContentTemplate>
<TabItem Header="Tab1"/>
<TabItem Header="Tab2"/>
</TabControl>
Run Code Online (Sandbox Code Playgroud)
它将创建一个带有两个模板化选项卡的 TabControl。现在在文本框中输入一些内容并切换到另一个选项卡,输入的文本将保留。现在每个选项卡将具有相同的内容。我没有在 ListBox 或任何其他控件中观察到相同的行为,这使得实际工作非常困难,因为每一点都需要绑定到 ViewModel 才能使其在 TabControl 中可用。当我在 DataTemplate 中使用的扩展器在我的所有选项卡中弹出时,我注意到了这种奇怪的行为,尽管我专门解决了一个问题。作为一种解决方法,我必须将“IsExpanded”绑定到 ViewModel 中的属性,但这样做确实很糟糕。
有人知道这里发生了什么事吗?
<TabControl x:Name="MainTab" SelectedIndex="0"/>
...
Collection.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Collection_CollectionChanged);
...
void Collection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
TabItem MyNewItem = new TabItem();
ContentPresenter MyContentPresenter = new ContentPresenter();
MyContentPresenter.ContentTemplate = (DataTemplate)this.FindResource("MyTemplate");
MyContentPresenter.Content = e.NewItems[0];
MyNewItem.Content = MyContentPresenter;
MainTab.Items.Add(MyNewItem ); …Run Code Online (Sandbox Code Playgroud) 有没有办法使 TabControl 上的最后一个选项卡右对齐?想让最后一个与前几个分开。
谢谢 !
我有一个TabControl允许用户管理以下文档的文件:

在某些时候,我想添加一个功能,允许用户浮动TabItems 并将它们停靠回与TabControl您在 Visual Studio 中可以做的事情差不多的地方。此功能将允许用户更轻松地比较文档并在它们之间复制/粘贴等。
我有一些关于如何去做这件事的一般想法。该TabControl有其ItemsSource必然的文档视图模型的列表。
要浮动选项卡:
Thumb控件添加到TabItem.Thumb,关联的文档视图模型将从TabControl列表中删除。Window被打开,与文档视图模型绑定,以显示/编辑该文档。要停靠选项卡:
DragOver事件处理程序TabControl以识别Window拖过选项卡条区域的文档。TabControl列表中。Window已关闭。有没有关于如何做到这一点的例子,或者你有办法做到这一点?
谢谢。
我正在研究 WPF,我正在创建一个 userControl,其中包含一个具有一些 TabItems 的 TabControl。
当所选的选项卡更改时,我需要执行一些东西,所以,我尝试做的是使用该事件,myTabControl.SelectionChanged但它是多次提出的,即使我只点击了一个tabItem。然后我读了这篇文章is-re-selected-tab-changed-event-in-the-standard-wpf-tab-control并将此代码放入我的方法中:
void mainTabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.Source is TabControl)
{
//do work when tab is changed
}
}
Run Code Online (Sandbox Code Playgroud)
这样做之后,第一个问题已经解决,但是当我运行应用程序并尝试更改选项卡时,出现了一个错误:
Dispatcher processing has been suspended, but messages are still being processed
Run Code Online (Sandbox Code Playgroud)
Visual Studio 指向内部的第一行代码 if (e.Source is TabControl) { //here }
但是我发现这篇文章selectionchanged-event-firing-exceptions-for-unknown-reasons并且我可以通过编写一些代码来解决这个问题,如下所示:
void mainTabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.Source is TabControl)
{
if (this.IsLoaded)
{
//do work when tab is changed
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是现在我遇到了另一个我无法解决的问题:
事件被触发两次!另一个奇怪的事情是,只有当我第一次尝试更改所选选项卡时,事件才会引发两次,但所选选项卡仍然相同 …
使用 MahApps.Metro AnimatedSingleRowTabControl 时如何更改选项卡的字体大小。
使用普通 TabControl 时,我的主题 TabItem(基于 MetroTabItem)覆盖字体大小,但这不适用于动画单行选项卡控件。我尝试在 XAML 中的控件上设置 fontsize 属性,但这也不起作用。
问候艾伦
我正在使用 Prism 4.1 编写一个复合应用程序,该应用程序使用 aTabControl作为在应用程序的主要模式之间切换的一种方式。我目前可以TabControl通过简单地导航到以该TabControl区域为目标的视图来将视图加载到单独的选项卡中:
在我的Shell.xaml:
<Window>
<Grid>
<TabControl prism:RegionManager.RegionName="TabRegion" />
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
在我Bootstrapper.cs的InitializeShell()方法中:
regionManager.Regions["TabRegion"].RequestNavigate("FirstTabView");
regionManager.Regions["TabRegion"].RequestNavigate("SecondTabView");
regionManager.Regions["TabRegion"].RequestNavigate("ThirdTabView");
Run Code Online (Sandbox Code Playgroud)
然而,当应用程序启动时,视图和(更重要的是)它们各自的 ViewModel 会立即实例化,而不是在选择视图的选项卡时。有没有办法将 Prism 配置为仅在其选项卡被激活时加载视图?
我尝试在单独的模块中定义视图,并使用InitializationMode.OnDemand参数加载模块,但这似乎没有任何效果;我假设这是因为该RequestNavigate方法足以激活模块。
任何想法将不胜感激!
我在 SO 上发现了有关此问题的多个问题,但是我仍然无法完全获得可靠的解决方案。这是我阅读答案后得出的结论。
XML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="300" Width="300" x:Name="this">
<TabControl IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Tabs, ElementName=this}" x:Name="TabControl"/>
</Window>
Run Code Online (Sandbox Code Playgroud)
背后代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var tabs = new ObservableCollection<string> {"Tab1", "Tab2", "Tab3"};
Tabs = CollectionViewSource.GetDefaultView(tabs);
Tabs.CurrentChanging += OnCurrentChanging;
Tabs.CurrentChanged += OnCurrentChanged;
Tabs.MoveCurrentToFirst();
CurrentTab = tabs.First();
}
private void OnCurrentChanging(object sender, CurrentChangingEventArgs e)
{
//only show message box when tab is changed by user input
if (!_cancelTabChange)
{
if (MessageBox.Show("Change tab?", "Message", MessageBoxButton.YesNo) == …Run Code Online (Sandbox Code Playgroud) 以下内容仅创建 的一个实例MyTabView。我通过在 MyTabView.xaml.cs 的构造函数中放置断点来确认这一点。该视图显示在一个选项卡中,无论我创建多少个选项卡,我只点击该构造函数一次。
<DataTemplate DataType="{x:Type vm:MyTabViewModel}" x:Shared="false">
<vw:MyTabView />
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
选项卡控制:
<TabControl
Grid.Row="1"
ItemsSource="{Binding Tabs}"
SelectedItem="{Binding SelectedTab}"
>
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayName}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl>
Run Code Online (Sandbox Code Playgroud)
这会导致所有选项卡反映共享未绑定到视图模型的任何状态:如果您移动GridSplitter,则所有其他选项卡中的情况都是相同的GridSplitter,因此用户会觉得您移动了所有选项卡。这太荒谬了。
我不明白。有什么办法可以TabControl同时使用多个相同类型的项目吗?
编辑:添加x:Shared="false"到DataTemplate.
更新:
所以我找到了一些修复方法,但我不太喜欢它们。我将考虑编写一个转换器来转换ObservableCollection<Object>为ObservableCollection<TabItem>- 有点像实时更新版本
coll.Select(vm => new TabItem() { Content = vm });
Run Code Online (Sandbox Code Playgroud)
...但我们会看看它是否喜欢TabItem从 获取实例ItemsSource。我的钱说不要赌它。但我们会看到。
更新2:花了一段时间才回到这个话题。交换选项卡项目集合的花招是有效的,但SelectedItem存在问题。事实证明,还有另一种解决方案(如下)不会产生该问题,并且还避免了创建必须镜像源集合中的更改的“中间人”集合的复杂性和愚蠢性。
tabcontrol ×10
wpf ×9
c# ×4
xaml ×3
datatemplate ×2
silverlight ×2
avalondock ×1
data-binding ×1
dock ×1
layout ×1
mvvm ×1
prism ×1