选项卡控件是图形用户界面中的控件,其包含在屏幕上共享相同空间的多个选项卡项。
我有一个带有文本框和数据网格视图的表单页面以及包含选项卡控件的其他表单。我想在第二个表单中添加第一个表单选项卡。我尝试编写要应用的表单的代码...
我需要制作TabControl,其选项卡成对划分。我已经制作了看起来像我需要的模板表单并且可以按照我需要的方式工作 但我当然需要了解选项卡按钮将位于右栏......
C# WinForm 使用 TabControls 时组织代码 [关闭]
我想知道是否有关于如何更好地组织 C# WinForm 代码而不是将所有代码放在 Form1 中的建议。 我目前使用的格式 #区域选项卡1 //tab1的代码 #
根据这个:示例代码 我创建了自己的 TabController 实现: 无效主(){ runApp(new MyApp()); } 类 MyApp 扩展 StatefulWidget { @覆盖 _MyAppState createStat...
我是 C# 新手,正在构建一个应用程序以多种方式与数据交互。我想为用户提供通过在主屏幕上的 TabControl 中显示和隐藏选项卡来自定义界面的机会...
我有WinForm,它有很多控件(tabcontrol,tabpage,datagridview,...等)。我想获取datagridview中的数据。设计的结构是这样的(TabControl会有很多TabPage,每个
在 WPF HandyControl TabControl 中自定义下拉内容
我正在使用 WPF HandyControl TabControl,当有太多选项卡无法容纳在可见区域中时,我想自定义下拉列表中显示的内容。目前,当制表符宽度 ex...
我正在创建一个事件来检查选项卡控件中的特定选项卡页是否处于活动状态。 重点是,如果选项卡控件中的选项卡页是当前选定的选项卡,则会触发事件。任何代码...
从 TabControl 中删除选项卡:错误 4 无法找到绑定源
我有一个带有特殊“+ tab”的 TabControl,其定义如下: 我有一个带有特殊“+ tab”的 TabControl,其定义如下: <TabControl x:Name="ProjectsTabControl"> <local:ProjectTabItem x:Name="AddProjectTabTabItem" Header="+" MouseUp="AddProjectButton_Click" PreviewMouseDown="AddProjectTabTabItem_PreviewMouseDown"/> </TabControl> “MouseDown”只是将鼠标事件参数标记为已处理(以防止选择选项卡)。 “Button_Click”添加了一个具有以下样式的新选项卡: <Window.Resources> <Style x:Key="CloseableTabItemStyle" TargetType="local:ProjectTabItem"> <Setter Property="HeaderTemplate"> <Setter.Value> <DataTemplate> <DockPanel> <TextBlock Text="{Binding}" Margin="0,0,5,0"/> <Button Content="X" Click="CloseButton_Click" Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ProjectTabItem}}}"/> </DockPanel> </DataTemplate> </Setter.Value> </Setter> </Style> </Window.Resources> 这些是我使用的“实际”选项卡。每个此类选项卡的标题中都有一个“关闭按钮”。如您所见,关闭按钮的标签设置为 ProjectTabItem 祖先。 我的CloseButton逻辑如下: private async void CloseButton_Click(object sender, RoutedEventArgs e) { if (sender is Button closeButton && closeButton.Tag is ProjectTabItem tabItem) { ProjectsTabControl.Items.Remove(tabItem); if (ProjectsTabControl.SelectedIndex == ProjectsTabControl.Items.Count - 1) { ProjectsTabControl.SelectedIndex--; } } } 这里的想法是防止选择+选项卡(但是,即使我选择+选项卡,我很快就会描述的问题也会发生)。 当我关闭最后一个选项卡(即+选项卡之前的最后一个选项卡)时,我看到以下错误 System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.TabControl', AncestorLevel='1''. BindingExpression:Path=TabStripPlacement; DataItem=null; target element is 'ProjectTabItem' (Name=''); target property is 'NoTarget' (type 'Object') 只有在关闭选项卡时选择该选项卡时才会发生这种情况。 似乎如果我在关闭“最后一个”选项卡之前先打开一个新选项卡,则问题不会发生。 (但是,这对我没有帮助,因为我希望除了 + 选项卡之外根本没有任何选项卡。) 这是什么原因造成的?我该如何解决它? 编辑:我想我已经找到了解决方法here。在删除选项卡之前设置 tabItem.Template = null; 实际上可以解决问题。那么让我将问题改为:为什么会发生这种情况?这个“解决方案”实际上是一个解决方案还是它只是抑制了我的代码中的一些潜在的重要问题? 只要您使用代码隐藏,您就永远无法享受 WPF 的乐趣。你总是会陷入“解决方法-陷阱”。如果您遵循 MVVM 模式,事情会变得容易得多。 我刚刚在我的应用程序中创建了一个 TabControl ,它绑定到一个 Observable Collection 在此可观察集合中是 TabItemModel: public class TabItemModel : ViewModelBase { private string _header; private ObservableObject _content; public string Header { get { return _header; } set { _header = value; RaisePropertyChanged(nameof(Header)); } } public ObservableObject Content { get { return _content; } set { _content = value; RaisePropertyChanged(nameof(Content)); } } private readonly IMessenger _messenger; public RelayCommand CloseTabCommand { get; set; } public TabItemModel(IMessenger messenger) { _messenger = messenger; CloseTabCommand = new RelayCommand(CloseThisTab); } private void CloseThisTab() { _messenger.Send(this); } } 这里是 XAML - 此 TabControl 的一部分: <TabControl Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1" Grid.RowSpan="2" ItemsSource="{Binding TabItems.Models}" SelectedItem="{Binding ActiveTab, Mode=TwoWay}"> <TabControl.ItemTemplate> <DataTemplate> <Border BorderBrush="Black" BorderThickness="2" CornerRadius="5" Margin="10,0,0,0"> <Grid Width="auto"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="9*"/> </Grid.ColumnDefinitions> <TextBlock Text="{Binding Header}" FontSize="12" FontWeight="DemiBold" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="12,0" Width="auto"/> <Button Grid.Column="1" Foreground="White" Command="{Binding CloseTabCommand}" HorizontalAlignment="Right" Padding="5" VerticalContentAlignment="Center" Margin="5"> <Button.Content> <Image Source="/icon-delete.png" Height="12" Width="12"/> </Button.Content> </Button> </Grid> </Border> </DataTemplate> </TabControl.ItemTemplate> MainViewModel 中的声明: [ObservableProperty] TabItemViewModel tabItems; [ObservableProperty] TabItemModel activeTab; XAML 中的按钮会触发 TabItemModel 中的 Relay-Command,该命令会向 View-Model 发送消息以关闭选项卡。我只是从集合中删除了这个特定的模型: public void Handle(TabItemModel message) { if (TabItems.Models.Count > 0) { TabItems.Models.Remove(message); } } 对我来说效果很好。
嗨,我一直在网上寻找一些选项卡按钮关闭功能,但所有这些解决方案都有一些复杂的事件处理程序,我想尝试保持简单,但我可能已经破坏了
我需要实现一个选项卡控件菜单。在每个选项卡中,我需要渲染用户在应用程序菜单中单击的页面。用户单击的所有页面必须渲染在选项卡控件内,而不是初始化...
该选项卡有 19 个组合框,每个组合框填充了大约 500 个项目,winforms 导致加载选项卡时出现相当多的延迟,有什么方法可以优化它,这只发生在网络上...
一个WPF MainWindow有四个内容相同的TabItem(一个View,ViewModel),如何告诉View它属于哪个TabItem?
我探索/学习 WPF/MVVM 的下一步将我带到了带有 TabControl 和四个 TabItem 的 MainWindow。每个选项卡都有相同的内容,在一个视图中定义一组四个复选框,结果...
任何人都可以帮助我我无法在选项卡控件 C# 中初始化我的选项卡页面的名称属性这是我的代码
使用(连接=新的SqlConnection(CS)) { SqlDataAdapter 适配器 = new SqlDataAdapter("SELECT category_name FROM book_category", Connection); ...
我在 SO 上发现了多个关于这个问题的问题,但是我仍然无法找到一个可靠的解决方案。这是我在阅读答案后想到的。 Xaml: 我在 SO 上发现了关于这个问题的多个问题,但是我仍然无法找到一个可靠的解决方案。这是我在阅读答案后想到的。 Xaml: <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> 背后的代码: 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) == MessageBoxResult.No) { _cancelTabChange = true; return; } } _cancelTabChange = false; } private void OnCurrentChanged(object sender, EventArgs e) { if (!_cancelTabChange) { //Update current tab property, if user did not cancel transition CurrentTab = (string)Tabs.CurrentItem; } else { //navigate back to current tab otherwise Dispatcher.BeginInvoke(new Action(() => Tabs.MoveCurrentTo(CurrentTab))); } } public string CurrentTab { get; set; } public static readonly DependencyProperty TabsProperty = DependencyProperty.Register("Tabs", typeof(ICollectionView), typeof(MainWindow), new FrameworkPropertyMetadata(default(ICollectionView))); public ICollectionView Tabs { get { return (ICollectionView)GetValue(TabsProperty); } set { SetValue(TabsProperty, value); } } private bool _cancelTabChange; } 基本上我想显示一条确认消息,当用户导航到不同的选项卡时,如果他单击“否” - 中止转换。但是这段代码不起作用。如果多次单击“Tab2”,每次都在消息框中选择“否”,它会在某个时候停止工作:事件停止触发。如果您单击“Tab3”,事件将再次触发,但如果您选择“是”,它将打开第二个选项卡而不是第三个选项卡。我无法弄清楚 wtf 是怎么回事。 :) 有人看到我的解决方案中有错误吗?或者有没有更简单的方法来显示确认消息,当用户切换选项卡?我也愿意使用任何具有适当 SelectionChanging 事件的开源选项卡控件。我找不到任何东西。 我正在使用.Net 4.0. 编辑: 如果我把消息框注释掉: 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) == MessageBoxResult.No) //{ Debug.WriteLine("Canceled"); _cancelTabChange = true; return; //} } _cancelTabChange = false; } 一切正常。奇怪。 这个解决方案来自web.archive 似乎与一起工作得很好 <TabControl ... yournamespace:SelectorAttachedProperties.IsSynchronizedWithCurrentItemFixEnabled="True" .../> private void OnCurrentChanging(object sender, CurrentChangingEventArgs e) { if (MessageBox.Show("Change tab?", "Message", MessageBoxButton.YesNo) == MessageBoxResult.No) { e.Cancel = true; } } public static class SelectorAttachedProperties { private static Type _ownerType = typeof(SelectorAttachedProperties); #region IsSynchronizedWithCurrentItemFixEnabled public static readonly DependencyProperty IsSynchronizedWithCurrentItemFixEnabledProperty = DependencyProperty.RegisterAttached("IsSynchronizedWithCurrentItemFixEnabled", typeof(bool), _ownerType, new PropertyMetadata(false, OnIsSynchronizedWithCurrentItemFixEnabledChanged)); public static bool GetIsSynchronizedWithCurrentItemFixEnabled(DependencyObject obj) { return (bool)obj.GetValue(IsSynchronizedWithCurrentItemFixEnabledProperty); } public static void SetIsSynchronizedWithCurrentItemFixEnabled(DependencyObject obj, bool value) { obj.SetValue(IsSynchronizedWithCurrentItemFixEnabledProperty, value); } private static void OnIsSynchronizedWithCurrentItemFixEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Selector selector = d as Selector; if (selector == null || !(e.OldValue is bool && e.NewValue is bool) || e.OldValue == e.NewValue) return; bool enforceCurrentItemSync = (bool)e.NewValue; ICollectionView collectionView = null; EventHandler itemsSourceChangedHandler = null; itemsSourceChangedHandler = delegate { collectionView = selector.ItemsSource as ICollectionView; if (collectionView == null) collectionView = CollectionViewSource.GetDefaultView(selector); }; SelectionChangedEventHandler selectionChangedHanlder = null; selectionChangedHanlder = delegate { if (collectionView == null) return; if (selector.IsSynchronizedWithCurrentItem == true && selector.SelectedItem != collectionView.CurrentItem) { selector.IsSynchronizedWithCurrentItem = false; selector.SelectedItem = collectionView.CurrentItem; selector.IsSynchronizedWithCurrentItem = true; } }; if (enforceCurrentItemSync) { TypeDescriptor.GetProperties(selector)["ItemsSource"].AddValueChanged(selector, itemsSourceChangedHandler); selector.SelectionChanged += selectionChangedHanlder; } else { TypeDescriptor.GetProperties(selector)["ItemsSource"].RemoveValueChanged(selector, itemsSourceChangedHandler); selector.SelectionChanged -= selectionChangedHanlder; } } #endregion IsSynchronizedWithCurrentItemFixEnabled } 出于某种原因,添加 TabControl.Focus() 可以解决问题: private void OnCurrentChanged(object sender, EventArgs e) { if (!_cancelTabChange) { //Update current tab property, if user did not cancel transition CurrentTab = (string)Tabs.CurrentItem; } else { //navigate back to current tab otherwise Dispatcher.BeginInvoke(new Action(() => { Tabs.MoveCurrentTo(CurrentTab); TabControl.Focus(); })); } } 我仍然不知道地球上到底发生了什么。所以我很乐意接受这个答案,这对这个问题有所启发。 在 tabControl_SelectionChanged 事件处理程序中: if (e.OriginalSource == tabControl) //if this event fired from your tabControl { e.Handled = true; if (!forbiddenPage.IsSelected) //User leaving the tab { if (forbiddenTest()) { forbiddenPage.IsSelected = true; MessageBox.Show("you must not leave this page"); } } 注意设置forbiddenPage.IsSelected = true会导致循环,你重新进入 这个事件处理程序。然而,这次我们退出,因为所选页面是禁止页面。 private void MainTabControl_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { if (ReasonBecauseLeaveTabItemIsForbidden) { if (MainTabControl.SelectedIndex == IndexOfTabItem) { MessageBox.Show(SomeMessageWhyLeaveTabItemIsForbidden); } MainTabControl.SelectedIndex = IndexOfTabItem; } } IndexOfTabItem - 因离开而禁用的 TabItem 的索引。 必须服从的人要求应用程序询问用户是否要离开页面,因此这里是稍微更改的代码: private Object _selectedTab; public Object SelectedTab { get { return _selectedTab; } set { if ( !(_selectedTab is ADR_Scanner.ViewModel.ConfigurationViewModel) || !_configurationViewModel.HasChanged || (System.Windows.Forms.MessageBox.Show("Are you sure you want to leave this page without saving the configuration changes", ADR_Scanner.App.Current.MainWindow.Title, System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Error) == System.Windows.Forms.DialogResult.Yes) ) { _selectedTab = value; } OnPropertyChanged("SelectedTab"); } } 我认为这个小改动几乎可以满足您的需求。 有一个更简单的解决方案。向 XAML 中的选定项添加绑定: <TabControl SelectedItem="{Binding SelectedTab}" ... 然后在视图模型中: private Object _selectedTab; public Object SelectedTab { get { return _selectedTab; } set { if (_selectedTab is ADR_Scanner.ViewModel.ConfigurationViewModel && _configurationViewModel.HasChanged) { System.Windows.Forms.MessageBox.Show("Please save the configuration changes", ADR_Scanner.App.ResourceAssembly.GetName().Name, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error); } else { _selectedTab = value; } OnPropertyChanged("SelectedTab"); } } 显然,您将 ADR_Scanner.ViewModel.ConfigurationViewModel 替换为您自己的视图模型类。最后确保在构造函数中初始化 _selectedTab,否则 TabControl 将没有初始选择。
标准WPF选项卡控件中是否有Selected Tab Changed事件
在 WPF 中,是否有一个事件可用于确定 TabControl 的选定选项卡何时更改? 我试过使用 TabControl.SelectionChanged 但它在孩子的
每次创建新标签时,内容都会出现,但当整个页面调整大小时,内容不会调整大小。它在没有课程的情况下工作正常,但每当我尝试将它与课程集成时......
ListView 和 TextBox OnPropertyChanged 工作正常但 Tab Control 不工作
过去几周,当我在列表视图文本框中更改值时,我努力解决在选项卡控件中进行更改的问题,反之亦然。 列表视图和文本框一切正常,但我不是...
我在 VB.NET 中使用左对齐的 TabControl 时出现奇怪的行为。截屏: 我想要的是让选项卡与向左旋转 90 度时的字面意思相同。 母鹿...
如何在c#回车代码中访问TabControl.ContentTemplate中的内容?
我写的是一个矢量编辑器。在我开始使用TabControl之前,一切都很正常。然而,有必要同时上传几个打开的文件。每个打开的文件都显示在TabItem上。...