WPF 自定义控件,将多个 ComboBox 值组合成单个 DependencyProperty
WPF Custom Control, Combine multiple ComboBox values into single DependencyProperty
我有一个带有两个 ComboBox 的自定义控件,其中包含硬编码的 ComboBoxItems,我希望能够通过单个 DependencyProperty 绑定到这些值,但似乎无法使绑定正常工作。也许我的方法有点离谱,但我应该怎么做才能让它发挥作用?
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:MyApp.Components">
<Style TargetType="{x:Type local:ContractLimitSelector}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ContractLimitSelector}">
<ControlTemplate.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</ControlTemplate.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<ComboBox x:Name="PART_ComboAA" Grid.Column="0" SelectedValue="{TemplateBinding SelectedAA}" />
<ComboBox x:Name="PART_ComboFA" Grid.Column="1" SelectedValue="{TemplateBinding SelectedFA}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
自定义控件:
public class SelectorItems
{
public string AA { get; set; }
public string FA { get; set; }
}
public class ContractLimitSelector : Control
{
private static List<string> ComboBoxSource = new List<string>()
{
"-",
"BE",
"EE",
};
static ContractLimitSelector()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ContractLimitSelector), new FrameworkPropertyMetadata(typeof(ContractLimitSelector)));
}
public override void OnApplyTemplate()
{
var comboAA = Template.FindName("PART_ComboAA", this) as ComboBox;
var comboFA = Template.FindName("PART_ComboFA", this) as ComboBox;
comboAA.ItemsSource = ComboBoxSource;
comboFA.ItemsSource = ComboBoxSource;
base.OnApplyTemplate();
}
private SelectorItems GetAllValues()
{
var AA = (string)GetValue(SelectedAAProperty);
var FA = (string)GetValue(SelectedFAProperty);
return new SelectorItems() { AA = AA, FA = FA };
}
public static readonly DependencyProperty VisibleHeaderProperty =
DependencyProperty.Register("VisibleHeader", typeof(bool), typeof(ContractLimitSelector),
new PropertyMetadata(false));
public bool VisibleHeader
{
get { return (bool)GetValue(VisibleHeaderProperty); }
set { SetValue(VisibleHeaderProperty, value); }
}
public static readonly DependencyProperty SelectedAAProperty =
DependencyProperty.Register("SelectedAA", typeof(string), typeof(ContractLimitSelector),
new PropertyMetadata(string.Empty));
public string SelectedAA
{
get { return (string)GetValue(SelectedAAProperty); }
set
{
var all = GetAllValues();
SetValue(SelectedValuesProperty, new SelectorItems() { AA = value, FA = all.FA, });
SetValue(SelectedAAProperty, value);
}
}
public static readonly DependencyProperty SelectedFAProperty =
DependencyProperty.Register("SelectedFA", typeof(string), typeof(ContractLimitSelector),
new PropertyMetadata(string.Empty));
public string SelectedFA
{
get { return (string)GetValue(SelectedFAProperty); }
set
{
var all = GetAllValues();
SetValue(SelectedValuesProperty, new SelectorItems() { AA = all.AA, FA = value, });
SetValue(SelectedFAProperty, value);
}
}
public SelectorItems SelectedValues
{
get
{
return new SelectorItems()
{
AA = (string)GetValue(SelectedAAProperty),
FA = (string)GetValue(SelectedFAProperty),
};
}
set
{
SetValue(SelectedAAProperty, value.AA);
SetValue(SelectedFAProperty, value.FA);
}
}
public static readonly DependencyProperty SelectedValuesProperty =
DependencyProperty.Register("SelectedValues", typeof(SelectorItems), typeof(ContractLimitSelector),
new PropertyMetadata(new SelectorItems()));
}
我是这样使用的:
XAML:
<custom:ContractLimitSelector SelectedValues="{Binding PrepareLockHouseValue, Mode=TwoWay}" />
视图模型:
private SelectorItems _contractValues;
public SelectorItems ContractValues
{
get
{
return _contractValues;
}
set
{
_contractValues = value;
OnPropertyChanged(nameof(ContractValues));
}
}
我认为每当组合框的任何更改都会触发“共享”SelectedValues DependecyProperty 时使用 SetValue,但没有任何东西被触发...
我错过了什么?
当您调用
时,SelectedAA
和SelectedFA
属性设置器不会被调用
SetValue(SelectedAAProperty, value.AA);
SetValue(SelectedFAProperty, value.FA);
你必须写
SelectedAA = value.AA;
SelectedFA = value.FA;
最好移动除
以外的所有代码
SetValue(SelectedAAProperty, value);
和
SetValue(SelectedFAProperty, value);
在 setter 之外并添加 PropertyChangedCallbacks 以执行其他代码。
这些属性也可以正确地与数据绑定和其他可能的值源一起使用。
通常,依赖项 属性 的 CLR 包装器的 get 和 set 方法不能包含除 GetValue
和 SetValue
调用之外的任何内容,因为 get/set 可能会被框架绕过。
我有一个带有两个 ComboBox 的自定义控件,其中包含硬编码的 ComboBoxItems,我希望能够通过单个 DependencyProperty 绑定到这些值,但似乎无法使绑定正常工作。也许我的方法有点离谱,但我应该怎么做才能让它发挥作用?
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:MyApp.Components">
<Style TargetType="{x:Type local:ContractLimitSelector}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ContractLimitSelector}">
<ControlTemplate.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</ControlTemplate.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<ComboBox x:Name="PART_ComboAA" Grid.Column="0" SelectedValue="{TemplateBinding SelectedAA}" />
<ComboBox x:Name="PART_ComboFA" Grid.Column="1" SelectedValue="{TemplateBinding SelectedFA}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
自定义控件:
public class SelectorItems
{
public string AA { get; set; }
public string FA { get; set; }
}
public class ContractLimitSelector : Control
{
private static List<string> ComboBoxSource = new List<string>()
{
"-",
"BE",
"EE",
};
static ContractLimitSelector()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ContractLimitSelector), new FrameworkPropertyMetadata(typeof(ContractLimitSelector)));
}
public override void OnApplyTemplate()
{
var comboAA = Template.FindName("PART_ComboAA", this) as ComboBox;
var comboFA = Template.FindName("PART_ComboFA", this) as ComboBox;
comboAA.ItemsSource = ComboBoxSource;
comboFA.ItemsSource = ComboBoxSource;
base.OnApplyTemplate();
}
private SelectorItems GetAllValues()
{
var AA = (string)GetValue(SelectedAAProperty);
var FA = (string)GetValue(SelectedFAProperty);
return new SelectorItems() { AA = AA, FA = FA };
}
public static readonly DependencyProperty VisibleHeaderProperty =
DependencyProperty.Register("VisibleHeader", typeof(bool), typeof(ContractLimitSelector),
new PropertyMetadata(false));
public bool VisibleHeader
{
get { return (bool)GetValue(VisibleHeaderProperty); }
set { SetValue(VisibleHeaderProperty, value); }
}
public static readonly DependencyProperty SelectedAAProperty =
DependencyProperty.Register("SelectedAA", typeof(string), typeof(ContractLimitSelector),
new PropertyMetadata(string.Empty));
public string SelectedAA
{
get { return (string)GetValue(SelectedAAProperty); }
set
{
var all = GetAllValues();
SetValue(SelectedValuesProperty, new SelectorItems() { AA = value, FA = all.FA, });
SetValue(SelectedAAProperty, value);
}
}
public static readonly DependencyProperty SelectedFAProperty =
DependencyProperty.Register("SelectedFA", typeof(string), typeof(ContractLimitSelector),
new PropertyMetadata(string.Empty));
public string SelectedFA
{
get { return (string)GetValue(SelectedFAProperty); }
set
{
var all = GetAllValues();
SetValue(SelectedValuesProperty, new SelectorItems() { AA = all.AA, FA = value, });
SetValue(SelectedFAProperty, value);
}
}
public SelectorItems SelectedValues
{
get
{
return new SelectorItems()
{
AA = (string)GetValue(SelectedAAProperty),
FA = (string)GetValue(SelectedFAProperty),
};
}
set
{
SetValue(SelectedAAProperty, value.AA);
SetValue(SelectedFAProperty, value.FA);
}
}
public static readonly DependencyProperty SelectedValuesProperty =
DependencyProperty.Register("SelectedValues", typeof(SelectorItems), typeof(ContractLimitSelector),
new PropertyMetadata(new SelectorItems()));
}
我是这样使用的: XAML:
<custom:ContractLimitSelector SelectedValues="{Binding PrepareLockHouseValue, Mode=TwoWay}" />
视图模型:
private SelectorItems _contractValues;
public SelectorItems ContractValues
{
get
{
return _contractValues;
}
set
{
_contractValues = value;
OnPropertyChanged(nameof(ContractValues));
}
}
我认为每当组合框的任何更改都会触发“共享”SelectedValues DependecyProperty 时使用 SetValue,但没有任何东西被触发...
我错过了什么?
当您调用
时,SelectedAA
和SelectedFA
属性设置器不会被调用
SetValue(SelectedAAProperty, value.AA);
SetValue(SelectedFAProperty, value.FA);
你必须写
SelectedAA = value.AA;
SelectedFA = value.FA;
最好移动除
以外的所有代码SetValue(SelectedAAProperty, value);
和
SetValue(SelectedFAProperty, value);
在 setter 之外并添加 PropertyChangedCallbacks 以执行其他代码。
这些属性也可以正确地与数据绑定和其他可能的值源一起使用。
通常,依赖项 属性 的 CLR 包装器的 get 和 set 方法不能包含除 GetValue
和 SetValue
调用之外的任何内容,因为 get/set 可能会被框架绕过。