WPF_CustomControl之拥有Visible属性的ColumnDefinition或者RowDefinition
一、背景
在WPF中布局的时候我们会经常用到ColumnDefinition,但是这个控件没有Visible属性,用来控制ColumnDefinition控件是否显示。
二、思路
ColumnDefinition控件本身是没有Visible属性的,所以我们需要自定义一个控件,这个控件继承ColumnDefinition,然后需要自定义一个bool类型的依赖属性Visible。
Visible属性的默认值为true;当Visible设置为false的时候,需要把Width属性设置为零,同时还需要把MinWidth属性也设置为零。这里有一个细节需要注意,但设置Width值的时候,实际设置的值会是Width和MinWidth值的最小值。所以Width属性设置为零的同时还需要把MinWidth属性也设置为零;当Visible设置为true的时候,那么Width值和MinWidth值设置为其对应的值就行。
三、实现
1、首先在WPF中创建自定义控件,会生成一个cs文件,然后修改父类为ColumnDefinition
public class ColumnDefinitionExtended : System.Windows.Controls.ColumnDefinition
{
static ColumnDefinitionExtended()
{
}
}
2、注册一个bool类型的依赖属性
public bool Visible
{
get { return (bool)GetValue(VisibleProperty); }
set { SetValue(VisibleProperty, value); }
}
// Using a DependencyProperty as the backing store for Visible. This enables animation, styling, binding, etc...
public static readonly DependencyProperty VisibleProperty =
DependencyProperty.Register("Visible", typeof(bool), typeof(ColumnDefinitionExtended),
new PropertyMetadata(true, new PropertyChangedCallback(OnVisibleChanged)));
private static void OnVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
注册依赖属性的时候PropertyMetadata类型的参数使用有回调函数的那一个。表示当改变Visible属性的时候会被触发。通过上面的分析思路,我们应该要在回调函数里进行校验,校验Width属性和MinWidth属性的值,所以我们需要提供校验函数。
3、注册Width和MinWidth的校验函数
static ColumnDefinitionExtended()
{
WidthProperty.OverrideMetadata(typeof(ColumnDefinitionExtended),
new FrameworkPropertyMetadata(new GridLength(0), null, new CoerceValueCallback(CoerceWidth)));
MinWidthProperty.OverrideMetadata(typeof(ColumnDefinitionExtended),
new FrameworkPropertyMetadata((double)0, null, new CoerceValueCallback(CoerceMinWidth)));
}
校验函数的实现:
private static object CoerceMinWidth(DependencyObject d, object baseValue)
{
return ((ColumnDefinitionExtended)d).Visible ? baseValue : (Double)0;
}
private static object CoerceWidth(DependencyObject d, object baseValue)
{
return ((ColumnDefinitionExtended)d).Visible ? baseValue : new GridLength(0);
}
4、调用校验函数
private static void OnVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
d.CoerceValue(ColumnDefinition.WidthProperty);
d.CoerceValue(ColumnDefinition.MinWidthProperty);
}
5、完整cs文件代码
public class ColumnDefinitionExtended : ColumnDefinition
{
static ColumnDefinitionExtended()
{
WidthProperty.OverrideMetadata(typeof(ColumnDefinitionExtended),
new FrameworkPropertyMetadata(new GridLength(0), null, new CoerceValueCallback(CoerceWidth)));
MinWidthProperty.OverrideMetadata(typeof(ColumnDefinitionExtended),
new FrameworkPropertyMetadata((double)0, null, new CoerceValueCallback(CoerceMinWidth)));
}
private static object CoerceMinWidth(DependencyObject d, object baseValue)
{
return ((ColumnDefinitionExtended)d).Visible ? baseValue : (Double)0;
}
private static object CoerceWidth(DependencyObject d, object baseValue)
{
return ((ColumnDefinitionExtended)d).Visible ? baseValue : new GridLength(0);
}
public bool Visible
{
get { return (bool)GetValue(VisibleProperty); }
set { SetValue(VisibleProperty, value); }
}
// Using a DependencyProperty as the backing store for Visible. This enables animation, styling, binding, etc...
public static readonly DependencyProperty VisibleProperty =
DependencyProperty.Register("Visible", typeof(bool), typeof(ColumnDefinitionExtended),
new PropertyMetadata(true, new PropertyChangedCallback(OnVisibleChanged)));
private static void OnVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
d.CoerceValue(WidthProperty);
d.CoerceValue(MinWidthProperty);
}
}
6、自定义的RowDefinition控件类似。
四、使用
1、在xaml文件中导入命令空间。例:
xmlns:cle="clr-namespace:ColumnDefinitionTest"
2、在Grid.ColumnDefinitions中使用。列:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<cle:ColumnDefinitionExtended Visible="{Binding ElementName=ck, Path=IsChecked}" Width="{Binding ElementName=slider, Path=Value}" MinWidth="50" MaxWidth="800" x:Name="Cde"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
五、效果