首先,我是一個業餘和非英語母語的人,所以我會很感激,如果你跟我有一點耐心;)TabControl的繼承CustomControl不顯示任何
繼另一個問題計算器,我做了一個TabControl,它擴展自己(像擴展器),只是修改原始TabControl的模板,所以我可以在選擇任何選項卡時更改控件的高度。
這工作完美,但需要邏輯的一些ViewModel屬性。現在我需要再次使用該控件,並且我認爲更好的方法是創建一個CustomControl。
我遇到的問題是,CustomControl只是無外觀,沒有風格適用於它,雖然我已經在Generic.xaml
文件中指定爲它的風格,和Build Action
財產Page
,修改了AsemblyInfo.cs
,以及所使用的DefaultStyleKeyProperty.OverrideMetadata
在靜態構造函數中。所有以下其他問題的建議。
我認爲最好是展示我現在使用的代碼,然後解釋我嘗試過的更多,我必須說當我注意到這一點時我正在編寫邏輯,所以現在它不工作。
Generic.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PRUEBA_TABBEDEXPANDER"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:ie="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:Core="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
xmlns:int="clr-namespace:System.Windows.Interactivity">
<SolidColorBrush x:Key="TabControlNormalBorderBrush" Color="#8C8E94"/>
<Style x:Key="TabItemFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="3,3,3,1" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="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="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 x:Key="TabItemStyle1" TargetType="{x:Type TabItem}">
<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 TabItem}">
<Grid SnapsToDevicePixels="true">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,1,1,0" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}">
<ToggleButton x:Name="Content" Content="{TemplateBinding Header}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:CallMethodAction MethodName="ToggleButton_Click"
TargetObject="{Binding RelativeSource={RelativeSource TemplatedParent}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ToggleButton>
<!--<ContentPresenter x:Name="Content" ContentSource="Header"
HorizontalAlignment="{Binding HorizontalContentAlignment,
RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{Binding VerticalContentAlignment,
RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>-->
</Border>
</Grid>
<ControlTemplate.Triggers>
<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,0,1,1"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Left">
<Setter Property="BorderThickness" TargetName="Bd" Value="1,1,0,1"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Right">
<Setter Property="BorderThickness" TargetName="Bd" Value="0,1,1,1"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="TabStripPlacement" Value="Top"/>
</MultiTrigger.Conditions>
<Setter Property="Margin" Value="-2,-2,-2,-1"/>
<Setter Property="Margin" TargetName="Content" Value="0,0,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,-2"/>
<Setter Property="Margin" TargetName="Content" Value="0,1,0,0"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="TabStripPlacement" Value="Left"/>
</MultiTrigger.Conditions>
<Setter Property="Margin" Value="-2,-2,-1,-2"/>
<Setter Property="Margin" TargetName="Content" Value="0,0,1,0"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="TabStripPlacement" Value="Right"/>
</MultiTrigger.Conditions>
<Setter Property="Margin" Value="-1,-2,-2,-2"/>
<Setter Property="Margin" TargetName="Content" Value="1,0,0,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>
<Style x:Key="TabbedExpanderTabControlStyle" TargetType="{x:Type TabControl}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Padding" Value="4,4,4,4"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{StaticResource TabControlNormalBorderBrush}"/>
<Setter Property="Background" Value="#F9F9F9"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="ItemContainerStyle" Value="{StaticResource TabItemStyle1}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="ColumnDefinition0"/>
<ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition x:Name="RowDefinition0" Height="Auto"/>
<RowDefinition x:Name="RowDefinition1" Height="*"/>
</Grid.RowDefinitions>
<TabPanel x:Name="HeaderPanel" Grid.Column="0" IsItemsHost="true" Margin="2,2,2,0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/>
<Border x:Name="ContentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
<ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="TabStripPlacement" Value="Bottom">
<Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/>
<Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
<Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/>
<Setter Property="Margin" TargetName="HeaderPanel" Value="2,0,2,2"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Left">
<Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
<Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
<Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/>
<Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/>
<Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/>
<Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
<Setter Property="Margin" TargetName="HeaderPanel" Value="2,2,0,2"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Right">
<Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
<Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
<Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/>
<Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/>
<Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/>
<Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/>
<Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
<Setter Property="Margin" TargetName="HeaderPanel" Value="0,2,2,2"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TabbedExpanderStyle" TargetType="{x:Type local:TabbedExpander}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:TabbedExpander}">
<Grid>
<TabControl Style="{StaticResource TabbedExpanderTabControlStyle}"></TabControl>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
TabbedExpander.cs:
public class TabbedExpander : TabControl, INotifyPropertyChanged
{
static TabbedExpander()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TabbedExpander), new FrameworkPropertyMetadata(typeof(TabbedExpander)));
}
#region dependency properties
public ObservableCollection<object> ItemsS
{
get { return (ObservableCollection<object>)GetValue(ItemsSProperty); }
set { SetValue(ItemsSProperty, value); }
}
// Using a DependencyProperty as the backing store for ItemsS. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ItemsSProperty =
DependencyProperty.Register("ItemsS", typeof(ObservableCollection<object>), typeof(TabbedExpander),
new PropertyMetadata(new ObservableCollection<object>(), OnItemsSPropertyChanged));
private static void OnItemsSPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TabbedExpander control = d as TabbedExpander;
var old = e.OldValue as ObservableCollection<object>;
if (old != null)
{
// Unsubscribe from CollectionChanged on the old collection
old.CollectionChanged -= control.ItemsSCollectionChanged;
}
var n = e.NewValue as ObservableCollection<object>;
if (n != null)
{
// Subscribe to CollectionChanged on the new collection
n.CollectionChanged += control.ItemsSCollectionChanged;
}
}
private void ItemsSCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Reset) base.Items.Clear();
if (e.NewItems != null)
{
foreach (object item in e.NewItems)
{
base.Items.Add(item);
}
}
if (e.OldItems != null)
{
foreach (object item in e.OldItems)
{
base.Items.RemoveAt(e.OldStartingIndex);
}
}
}
#region public
public bool IsExpanded
{
get { return (bool)GetValue(IsExpandedProperty); }
set { SetValue(IsExpandedProperty, value); }
}
public double EXPANDER_OFFSET
{
get { return (double)GetValue(EXPANDER_OFFSETProperty); }
set { SetValue(EXPANDER_OFFSETProperty, value); }
}
public int EXPANDER_MIN_HEIGHT
{
get { return (int)GetValue(EXPANDER_MIN_HEIGHTProperty); }
set { SetValue(EXPANDER_MIN_HEIGHTProperty, value); }
}
public int EXPANDER_MAX_HEIGHT
{
get { return (int)GetValue(EXPANDER_MAX_HEIGHTProperty); }
set { SetValue(EXPANDER_MAX_HEIGHTProperty, value); }
}
public int EXPANDER_NOTEXPANDED_HEIGHT
{
get { return (int)GetValue(EXPANDER_NOTEXPANDED_HEIGHTProperty); }
set { SetValue(EXPANDER_NOTEXPANDED_HEIGHTProperty, value); }
}
public double EXPANDER_EXPANDED_HEIGHT
{
get { return (double)GetValue(EXPANDER_EXPANDED_HEIGHTProperty); }
set { SetValue(EXPANDER_EXPANDED_HEIGHTProperty, value); }
}
#endregion
#region static
public static readonly DependencyProperty IsExpandedProperty =
DependencyProperty.Register("IsExpanded",
typeof(bool),
typeof(TabbedExpander),
new PropertyMetadata(false, OnIsExpandedChanged));
private static void OnIsExpandedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TabbedExpander control = d as TabbedExpander;
if ((bool)e.NewValue) control.Height = control.EXPANDER_EXPANDED_HEIGHT;
else control.Height = control.EXPANDER_NOTEXPANDED_HEIGHT;
}
public static readonly DependencyProperty EXPANDER_OFFSETProperty =
DependencyProperty.Register("EXPANDER_OFFSET",
typeof(double),
typeof(TabbedExpander),
new PropertyMetadata(102d, OnOffsetChanged));
private static void OnOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
public static readonly DependencyProperty EXPANDER_MIN_HEIGHTProperty =
DependencyProperty.Register("EXPANDER_MIN_HEIGHT",
typeof(int),
typeof(TabbedExpander),
new PropertyMetadata(96, OnMinHeightChanged));
private static void OnMinHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
public static readonly DependencyProperty EXPANDER_MAX_HEIGHTProperty =
DependencyProperty.Register("EXPANDER_MAX_HEIGHT",
typeof(int),
typeof(TabbedExpander),
new PropertyMetadata(400, OnMaxHeightChanged));
private static void OnMaxHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
public static readonly DependencyProperty EXPANDER_NOTEXPANDED_HEIGHTProperty =
DependencyProperty.Register("EXPANDER_NOTEXPANDED_HEIGHT",
typeof(int),
typeof(TabbedExpander),
new PropertyMetadata(30, OnNotExpandedHeightChanged));
private static void OnNotExpandedHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
public static readonly DependencyProperty EXPANDER_EXPANDED_HEIGHTProperty =
DependencyProperty.Register("EXPANDER_EXPANDED_HEIGHT",
typeof(double),
typeof(TabbedExpander),
new PropertyMetadata(100d, OnExpandedHeightChanged));
private static void OnExpandedHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
#endregion
#endregion
#region PropertyChanged
public event PropertyChangedEventHandler PropertyChanged = delegate { };
protected void NotifyPropChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.Height = this.EXPANDER_NOTEXPANDED_HEIGHT;
}
}
還有一點MainWindow.xaml
來進行測試:
<Window x:Class="PRUEBA_TABBEDEXPANDER.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PRUEBA_TABBEDEXPANDER"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:TabbedExpander TabStripPlacement="Top">
<TabItem Header="prueba1">
<TextBox Text="prueba1"/>
</TabItem>
</local:TabbedExpander>
</Grid>
這是我的最後一次嘗試,我第一次嘗試是直接套用TabbedExpanderTabControlStyle
樣式只是改變了TargetType
自定義控件,那麼我就沒有加入ItemsSProperty
,只是用TabControl
的嘗試繼承ItemsSource
具有相同的語法在「MainWindow.xaml`,並改變了語法:
<Grid>
<local:TabbedExpander TabStripPlacement="Top">
<local:TabbedExpander.ItemsS>
<TabItem Header="prueba1">
<TextBox Text="prueba1"/>
</TabItem>
</local:TabbedExpander.ItemsS>
</local:TabbedExpander>
</Grid>
除了<local:TabbedExpander.Items>
嘗試使用TabControl
的繼承Items
。
唯一有效的工作是將Generic.xaml
作爲ResourceDictionary
合併,並將TabbedExpanderTabControlStyle
直接應用於自定義控件...我認爲這不是正確的方法...對不對?因爲我將不得不將風格應用於每一個自定義控件,我將添加到我的應用程序...
我想我或者做錯了應用樣式,或使用tabitems集合,但現在我' ?m的想法:(
任何想法
的事情是,糾正我,如果我錯了,如果我這樣做,當我將自定義控件添加到應用程序中,我將不得不手動將樣式應用於其所有實例,對嗎? – Nox
對不起,我按回車沒有完成評論¬¬...我認爲,自定義控件風格將自動應用於所有實例,所以我應該找到辦法做到這一點。 – Nox
不應該,不。如果你沒有指定一個鍵,那麼所有目標類型的子類將繼承這個樣式。 – Joe