如何解决Customable TabControl for CloseableTabs
| 这里有一些“可关闭”选项卡的解决方案,但它们都依赖于集合的所有者来提供关闭功能。 我认为通过创建CustomTabControl
和TabItem
也许可以在CodeBehind中完成。
这个想法是要以某种方式提醒ѭ1中的TabControl
已按下关闭按钮(也许是冒泡事件或某些事,请提出建议),然后从ѭ5中取出包裹在ѭ1中的特定物品。
问题是我不确定如何或什至可行。您能以某种方式从TabControl
中的ItemsSource
集合中删除项目吗?也许我们可以设置一个新的DP母猪,我们可以完全控制Collection并将其设置为Code Behind中的ItemsSource
。
任何人都这样做或有任何想法要这样做。甚至有可能吗?
解决方法
即使在技术上可行,我还是建议您坚持使用M-V-VM。让集合的所有者,即ViewModel控件添加/删除集合中的项目。
让View变薄,并通过数据绑定与VM的集合同步。这样可以避免视图变得复杂,并消除了GUI,这阻碍了可测试性。
您应该发现这是WPF阻力最小的路径。
, 这出现在我们的应用程序中,所以我想我会发布我的解决方案。 ClosableTabControl通过从绑定的ItemsSource中删除项目来关闭任何选项卡。从其他溶液中将其部分刮掉(Szymon Kobalczyk等)。
ClosableTabControl.cs:
[StyleTypedProperty(Property = \"ItemContainerStyle\",StyleTargetType = typeof(ClosableTabItem))]
public class ClosableTabControl : TabControl
{
static ClosableTabControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ClosableTabControl),new FrameworkPropertyMetadata(typeof(ClosableTabControl)));
CloseTabCommand = new RoutedCommand();
}
public ClosableTabControl()
: base()
{
CommandBindings.Add(new CommandBinding(CloseTabCommand,CloseTabCommand_Execute));
}
public static ICommand CloseTabCommand { get; private set; }
private void CloseTabCommand_Execute(object sender,ExecutedRoutedEventArgs args)
{
if (args.Parameter == null || !(args.Parameter is ClosableTabItem))
throw new ArgumentNullException(\"parameter must be of type ClosableTabItem\");
var item = this.ItemContainerGenerator.ItemFromContainer((ClosableTabItem)args.Parameter);
if (item == null)
throw new InvalidOperationException(\"Item not in collection\");
IEditableCollectionView view = this.Items;
if (!view.CanRemove)
throw new InvalidOperationException(\"Read-only collection\");
view.Remove(item);
}
protected override DependencyObject GetContainerForItemOverride()
{
return new ClosableTabItem();
}
}
ClosableTabItem.cs:
public class ClosableTabItem : TabItem
{
static ClosableTabItem()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ClosableTabItem),new FrameworkPropertyMetadata(typeof(ClosableTabItem)));
}
}
主题/Generic.xaml:
<Style TargetType=\"{x:Type local:ClosableTabControl}\" BasedOn=\"{StaticResource {x:Type TabControl}}\" />
<Style x:Key=\"TabItemFocusVisual\">
<Setter Property=\"Control.Template\">
<Setter.Value>
<ControlTemplate>
<Rectangle SnapsToDevicePixels=\"true\" Stroke=\"Black\" StrokeDashArray=\"1 2\" StrokeThickness=\"1\" Margin=\"3,3,1\"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<SolidColorBrush x:Key=\"TabControlNormalBorderBrush\" Color=\"#8C8E94\"/>
<LinearGradientBrush x:Key=\"TabItemHotBackground\" EndPoint=\"0,1\" StartPoint=\"0,0\">
<GradientStop Color=\"#EAF6FD\" Offset=\"0.15\"/>
<GradientStop Color=\"#D9F0FC\" Offset=\".5\"/>
<GradientStop Color=\"#BEE6FD\" Offset=\".5\"/>
<GradientStop Color=\"#A7D9F5\" Offset=\"1\"/>
</LinearGradientBrush>
<SolidColorBrush x:Key=\"TabItemSelectedBackground\" Color=\"#F9F9F9\"/>
<SolidColorBrush x:Key=\"TabItemHotBorderBrush\" Color=\"#3C7FB1\"/>
<SolidColorBrush x:Key=\"TabItemDisabledBackground\" Color=\"#F4F4F4\"/>
<SolidColorBrush x:Key=\"TabItemDisabledBorderBrush\" Color=\"#FFC9C7BA\"/>
<Style TargetType=\"{x:Type local:ClosableTabItem}\">
<Style.Resources>
<LinearGradientBrush x:Key=\"ButtonNormalBackground\" EndPoint=\"0,0\">
<GradientStop Color=\"#F3F3F3\" Offset=\"0\"/>
<GradientStop Color=\"#EBEBEB\" Offset=\"0.5\"/>
<GradientStop Color=\"#DDDDDD\" Offset=\"0.5\"/>
<GradientStop Color=\"#CDCDCD\" Offset=\"1\"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key=\"ButtonOverBackground\" EndPoint=\"0,0\">
<GradientStop Color=\"#FFFAFAFA\" Offset=\"0\"/>
<GradientStop Color=\"#FFE0E0E3\" Offset=\"1\"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key=\"ButtonPressedBackground\" EndPoint=\"0,0\">
<GradientStop Color=\"#FFE0E0E2\" Offset=\"0\"/>
<GradientStop Color=\"#FFF8F8F8\" Offset=\"1\"/>
</LinearGradientBrush>
<SolidColorBrush x:Key=\"ButtonNormalBorder\" Color=\"#FF969696\"/>
<Style x:Key=\"CloseableTabItemButtonStyle\" TargetType=\"{x:Type Button}\">
<Setter Property=\"FocusVisualStyle\" Value=\"{x:Null}\"/>
<Setter Property=\"Background\" Value=\"{StaticResource ButtonNormalBackground}\"/>
<Setter Property=\"BorderBrush\" Value=\"{StaticResource ButtonNormalBorder}\"/>
<Setter Property=\"BorderThickness\" Value=\"1\"/>
<Setter Property=\"Foreground\" Value=\"{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}\"/>
<Setter Property=\"HorizontalContentAlignment\" Value=\"Center\"/>
<Setter Property=\"VerticalContentAlignment\" Value=\"Center\"/>
<Setter Property=\"Padding\" Value=\"4\"/>
<Setter Property=\"Template\">
<Setter.Value>
<ControlTemplate TargetType=\"{x:Type Button}\">
<Grid>
<Border SnapsToDevicePixels=\"true\" x:Name=\"Chrome\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" CornerRadius=\"2\" Opacity=\"0\" />
<ContentPresenter SnapsToDevicePixels=\"{TemplateBinding SnapsToDevicePixels}\" HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" Margin=\"{TemplateBinding Padding}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\" RecognizesAccessKey=\"True\"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property=\"IsMouseOver\" Value=\"True\">
<Setter Property=\"Opacity\" TargetName=\"Chrome\" Value=\"1\"/>
<Setter Property=\"Background\" TargetName=\"Chrome\" Value=\"{DynamicResource ButtonOverBackground}\" />
</Trigger>
<Trigger Property=\"IsPressed\" Value=\"True\">
<Setter Property=\"Opacity\" TargetName=\"Chrome\" Value=\"1\"/>
<Setter Property=\"Background\" TargetName=\"Chrome\" Value=\"{DynamicResource ButtonPressedBackground}\" />
</Trigger>
<Trigger Property=\"IsEnabled\" Value=\"false\">
<Setter Property=\"Foreground\" Value=\"#ADADAD\"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource TabItemFocusVisual}\"/>
<Setter Property=\"Foreground\" Value=\"Black\"/>
<Setter Property=\"Padding\" Value=\"6,1,6,1\"/>
<Setter Property=\"BorderBrush\" Value=\"{StaticResource TabControlNormalBorderBrush}\"/>
<Setter Property=\"Background\" Value=\"{StaticResource ButtonNormalBackground}\"/>
<Setter Property=\"HorizontalContentAlignment\" Value=\"Stretch\"/>
<Setter Property=\"VerticalContentAlignment\" Value=\"Stretch\"/>
<Setter Property=\"Template\">
<Setter.Value>
<ControlTemplate TargetType=\"{x:Type local:ClosableTabItem}\">
<Grid SnapsToDevicePixels=\"true\">
<Border x:Name=\"Bd\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"1,0\" >
<DockPanel x:Name=\"ContentPanel\">
<Button x:Name=\"PART_Close\" HorizontalAlignment=\"Center\" Margin=\"3,0\" VerticalAlignment=\"Center\" Width=\"16\" Height=\"16\" DockPanel.Dock=\"Right\" Style=\"{DynamicResource CloseableTabItemButtonStyle}\" ToolTip=\"Close\" Command=\"{x:Static local:ClosableTabControl.CloseTabCommand}\" CommandParameter=\"{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ClosableTabItem}}}\">
<Path x:Name=\"Path\" Stretch=\"Fill\" StrokeThickness=\"0.5\" Stroke=\"#FF333333\" Fill=\"#FF969696\" Data=\"F1 M 2.28484e-007,1.33331L 1.33333,0L 4.00001,2.66669L 6.66667,6.10352e-005L 8,1.33331L 5.33334,4L 8,6.66669L 6.66667,8L 4,5.33331L 1.33333,8L 1.086e-007,6.66669L 2.66667,4L 2.28484e-007,1.33331 Z \" HorizontalAlignment=\"Stretch\" VerticalAlignment=\"Stretch\"/>
</Button>
<ContentPresenter x:Name=\"Content\" SnapsToDevicePixels=\"{TemplateBinding SnapsToDevicePixels}\" ContentSource=\"Header\" RecognizesAccessKey=\"True\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" Margin=\"{TemplateBinding Padding}\"/>
</DockPanel>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property=\"IsMouseOver\" SourceName=\"PART_Close\" Value=\"True\">
<Setter Property=\"Fill\" TargetName=\"Path\" Value=\"#FFB83C3D\"/>
</Trigger>
<Trigger Property=\"IsPressed\" SourceName=\"PART_Close\" Value=\"True\">
<Setter Property=\"Fill\" TargetName=\"Path\" Value=\"#FF9D3838\"/>
</Trigger>
<Trigger Property=\"IsMouseOver\" Value=\"true\">
<Setter Property=\"Background\" TargetName=\"Bd\" Value=\"{StaticResource TabItemHotBackground}\"/>
</Trigger>
<Trigger Property=\"IsSelected\" Value=\"true\">
<Setter Property=\"Panel.ZIndex\" Value=\"1\"/>
<Setter Property=\"Background\" TargetName=\"Bd\" Value=\"{StaticResource TabItemSelectedBackground}\"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property=\"IsSelected\" Value=\"false\"/>
<Condition Property=\"IsMouseOver\" Value=\"true\"/>
</MultiTrigger.Conditions>
<Setter Property=\"BorderBrush\" TargetName=\"Bd\" Value=\"{StaticResource TabItemHotBorderBrush}\"/>
</MultiTrigger>
<Trigger Property=\"TabStripPlacement\" Value=\"Bottom\">
<Setter Property=\"BorderThickness\" TargetName=\"Bd\" Value=\"1,1\"/>
</Trigger>
<Trigger Property=\"TabStripPlacement\" Value=\"Left\">
<Setter Property=\"BorderThickness\" TargetName=\"Bd\" Value=\"1,1\"/>
</Trigger>
<Trigger Property=\"TabStripPlacement\" Value=\"Right\">
<Setter Property=\"BorderThickness\" TargetName=\"Bd\" Value=\"0,1\"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property=\"IsSelected\" Value=\"true\"/>
<Condition Property=\"TabStripPlacement\" Value=\"Top\"/>
</MultiTrigger.Conditions>
<Setter Property=\"Margin\" Value=\"-2,-2,-1\"/>
<Setter Property=\"Margin\" TargetName=\"ContentPanel\" Value=\"0,1\"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property=\"IsSelected\" Value=\"true\"/>
<Condition Property=\"TabStripPlacement\" Value=\"Bottom\"/>
</MultiTrigger.Conditions>
<Setter Property=\"Margin\" Value=\"-2,-1,-2\"/>
<Setter Property=\"Margin\" TargetName=\"ContentPanel\" Value=\"0,0\"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property=\"IsSelected\" Value=\"true\"/>
<Condition Property=\"TabStripPlacement\" Value=\"Left\"/>
</MultiTrigger.Conditions>
<Setter Property=\"Margin\" Value=\"-2,0\"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property=\"IsSelected\" Value=\"true\"/>
<Condition Property=\"TabStripPlacement\" Value=\"Right\"/>
</MultiTrigger.Conditions>
<Setter Property=\"Margin\" Value=\"-1,-2\"/>
<Setter Property=\"Margin\" TargetName=\"ContentPanel\" Value=\"1,0\"/>
</MultiTrigger>
<Trigger Property=\"IsEnabled\" Value=\"false\">
<Setter Property=\"Background\" TargetName=\"Bd\" Value=\"{StaticResource TabItemDisabledBackground}\"/>
<Setter Property=\"BorderBrush\" TargetName=\"Bd\" Value=\"{StaticResource TabItemDisabledBorderBrush}\"/>
<Setter Property=\"Foreground\" Value=\"{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}\"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。