我有以下枚举:
[Flags]
public enum SubscriberLevel {
BRONZE = 1,
SILVER1 = 2,
SILVER2 = 4,
SILVER = SubscriberLevel.SILVER1 | SubscriberLevel.SILVER2,
GOLD1 = 8,
GOLD2 = 16,
GOLD3 = 32,
GOLD = SubscriberLevel.GOLD1 | SubscriberLevel.GOLD2 | SubscriberLevel.GOLD3,
DIAMOND1 = 64,
DIAMOND2 = 128,
DIAMOND3 = 256,
DIAMOND = SubscriberLevel.DIAMOND1 | SubscriberLevel.DIAMOND2 | SubscriberLevel.DIAMOND3,
ALL = SubscriberLevel.BRONZE | SubscriberLevel.SILVER | SubscriberLevel.GOLD | SubscriberLevel.DIAMOND
}
我正在开发一个控件,它应该允许用户通过一系列复选框来指示此枚举中的一个,多个或所有标志,列表中的每个枚举都有一个复选框。
我在控件中有一个Enum成员,以及一个公开Enum的属性。 控件本身继承了INotifyPropertyChanged方法,并且在设置值时,属性的Setter正确调用OnPropertyChanged事件处理程序。
我甚至在控件中看到了一些相似的功能,但我看不到它的表现是否正常:
说出用户所以取消选中ALL选项;我希望每个复选框都通过清除来反映这一点,但我没有看到这种情况发生。
截至目前,我认为我的问题是我将这些复选框的Checked状态绑定到Enum本身,我需要做的是将Enum绑定到这些选中的复选框,并让每个复选框代表枚举集中的特定标志。
我已经注意到在调试控件时,当取消选中复选框时,该值未设置。那是为什么?
我知道我需要使用转换器才能完成此任务,但目前还是如此;我如何在XAML方面实现这一目标;将控件的Datacontext定义为控件本身,然后将Enum标志绑定到各自的复选框?
这是其中一个复选框的示例:
<CheckBox
x:Name="chkAll" Grid.Row="1" VerticalContentAlignment="Center" VerticalAlignment="Center"
IsChecked="{Binding Path=SubLevel, Converter={StaticResource ETBC},
ConverterParameter={x:Static Enums:SubscriberLevel.ALL}, Mode=TwoWay}"/>
这是转换器:
public class EnumToBoolConverter : IValueConverter {
public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) {
return ( ( Enum )value ).HasFlag( ( Enum )parameter );
}
public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture ) {
return value.Equals( true ) ? parameter : Binding.DoNothing;
}
}
这是控件的代码(原样):
public partial class UCSubscriptionLevels : UserControl, INotifyPropertyChanged {
private SubscriberLevel _SubLevel = SubscriberLevel.ALL;
public event PropertyChangedEventHandler PropertyChanged;
public UCSubscriptionLevels( ) { InitializeComponent( ); }
/// <summary>
/// Get or Set Subscriber Levels to Build.
/// </summary>
public SubscriberLevel SubLevel {
get { return this._SubLevel; }
set {
this._SubLevel = value;
if ( this.PropertyChanged != null )
this.PropertyChanged( this, new PropertyChangedEventArgs( "SubLevel" ) );
}
}
}
已经有一段时间了;我忘记了依赖属性,所以我选择在控件而不是属性成员上实现依赖属性。这种行为仍然是粗略的。这是控件中属性的新代码:
public static readonly DependencyProperty SubscriberLevelProperty =
DependencyProperty.Register( "SubLevel", typeof( SubscriberLevel ),
typeof( UCSubscriptionLevels ), new PropertyMetadata( SubscriberLevel.ALL ) );
.
.
.
/// <summary>
/// Get or Set Subscriber Levels to Build.
/// </summary>
public SubscriberLevel SubLevel {
get { return ( SubscriberLevel )this.GetValue( UCSubscriptionLevels.SubscriberLevelProperty ); }
set { this.SetValue( UCSubscriptionLevels.SubscriberLevelProperty, value ); }
}
然而,它仍然表现不佳...
也;我不得不改变枚举(青铜= 0到1等)。
答案 0 :(得分:0)
好;这是一种非常烦人的解决方法,可能与你可以获得的CORRECT解决方案相去甚远,但我能够设想一种方法来处理我想要做的事情。这一切都在后面的代码中完成;在XAML中根本没有发生任何约束。
首先是依赖属性:
public static readonly DependencyProperty SubscriberLevelProperty =
DependencyProperty.Register( "SubLevel", typeof( SubscriberLevel ),
typeof( UCSubscriptionLevels ), new FrameworkPropertyMetadata( SubscriberLevel.ALL, FrameworkPropertyMetadataOptions.None, ( S, E ) => {
SubscriberLevel NV = ( SubscriberLevel )E.NewValue;
UCSubscriptionLevels sender = S as UCSubscriptionLevels;
sender.GetAllChildren<CheckBox>( ).ToList( ).ForEach( chk => {
chk.Checked -= sender.CheckedChanged;
chk.Unchecked -= sender.CheckedChanged;
chk.IsChecked = NV.HasFlag( sender.dctChkSL[chk] );
chk.Checked += new RoutedEventHandler( sender.CheckedChanged );
chk.Unchecked += new RoutedEventHandler( sender.CheckedChanged );
} );
} ) );
这里的主要变化是该属性本身处理传入的数据更改。我之前已经做过其他事情并且取得了一定程度的成功,所以我在这里试了一下。
在Loaded事件中,控件会为每个Checkbox Checked和Unchecked事件添加一个事件处理程序。此回调删除该事件处理程序(以避免无限循环),调整已检查状态,以便在控件字典中找到它时,将其标记为已选中;否则,取消选中它,然后再次将事件处理程序添加到事件中。
所有事件处理程序都是,
private void CheckedChanged( object sender, RoutedEventArgs e ) { this.SubLevel ^= this.dctChkSL[sender as CheckBox]; }.
这是字典:
private Dictionary<CheckBox, SubscriberLevel> dctChkSL;
这是字典和Checkboxes Checked / Unchecked事件处理程序的初始化程序。
this.dctChkSL = new Dictionary<CheckBox, SubscriberLevel>( ) {
{this.chkAll, SubscriberLevel.ALL}, {this.chkBronze, SubscriberLevel.BRONZE},
{this.chkSilver, SubscriberLevel.SILVER}, {this.chkSilver1, SubscriberLevel.SILVER1},
{this.chkSilver2, SubscriberLevel.SILVER2},
{this.chkGold, SubscriberLevel.GOLD}, {this.chkGold1, SubscriberLevel.GOLD1},
{this.chkGold2, SubscriberLevel.GOLD2}, {this.chkGold3, SubscriberLevel.GOLD3},
{this.chkDiamond, SubscriberLevel.DIAMOND}, {this.chkDiamond1, SubscriberLevel.DIAMOND1},
{this.chkDiamond2, SubscriberLevel.DIAMOND2}, {this.chkDiamond3, SubscriberLevel.DIAMOND3}
};
this.Loaded += ( S, E ) =>
this.GetAllChildren<CheckBox>( ).ToList( ).ForEach( chk => {
chk.Checked += new RoutedEventHandler( this.CheckedChanged );
chk.Unchecked += new RoutedEventHandler( this.CheckedChanged );
} );
尽管我希望有一个更有说服力的解决方案,因为我无法找到一个解决方案,但这必须要做,直到有人能提供更好的答案。