Ben bayrakları numaralandırma (teşekkürler Ian Oakes, original MSDN post) bağımsız bir bit için bir onay kutusu bağlama iki yönlü bir neredeyse işlevsel bir örnek var. Sorun ise, bağlamanın tek yönlü olduğu gibi davranmasıdır (DataContext için UI, tersi değil). Bu nedenle etkin bir şekilde onay kutusu başlatılmaz, ancak eğer değiştirilirse veri kaynağı doğru şekilde güncellenir. Ekli, bit tabanlı bağlamayı etkinleştirmek için bağlı bazı bağımlılık özelliklerini tanımlayan sınıftır. Fark ettiğim şey, DataContext'i değiştirmeye zorladığımda bile ValueChanged'in hiçbir zaman çağrılmadığıdır. Dayak, Açıkça Cilt Mod = TwoWay ayarı DataContext güncellemelerini, herhangi bir makul FrameworkMetadataPropertyOptions (AffectsRender, BindsTwoWayByDefault), dışarı kaynamaktadır onaylamak için bir etiket ve metin kutusu kullanarak, mülkiyet tanımları sırasını değiştirme: denedim ne
duvardaki kafa, anlaşmazlık durumunda ValueProperty'yi EnumValueProperty olarak değiştirin.
Önerebileceğiniz herhangi bir şey için herhangi bir öneri veya fikir son derece takdir edilecektir!
numaralandırma:
[Flags]
public enum Department : byte
{
None = 0x00,
A = 0x01,
B = 0x02,
C = 0x04,
D = 0x08
} // end enum Department
XAML kullanımı:
CheckBox Name="studentIsInDeptACheckBox"
ctrl:CheckBoxFlagsBehaviour.Mask="{x:Static c:Department.A}"
ctrl:CheckBoxFlagsBehaviour.IsChecked="{Binding Path=IsChecked, RelativeSource={RelativeSource Self}}"
ctrl:CheckBoxFlagsBehaviour.Value="{Binding Department}"
sınıfı:
///
/// A helper class for providing bit-wise binding.
///
public class CheckBoxFlagsBehaviour
{
private static bool isValueChanging;
public static Enum GetMask(DependencyObject obj)
{
return (Enum)obj.GetValue(MaskProperty);
} // end GetMask
public static void SetMask(DependencyObject obj, Enum value)
{
obj.SetValue(MaskProperty, value);
} // end SetMask
public static readonly DependencyProperty MaskProperty =
DependencyProperty.RegisterAttached("Mask", typeof(Enum),
typeof(CheckBoxFlagsBehaviour), new UIPropertyMetadata(null));
public static Enum GetValue(DependencyObject obj)
{
return (Enum)obj.GetValue(ValueProperty);
} // end GetValue
public static void SetValue(DependencyObject obj, Enum value)
{
obj.SetValue(ValueProperty, value);
} // end SetValue
public static readonly DependencyProperty ValueProperty =
DependencyProperty.RegisterAttached("Value", typeof(Enum),
typeof(CheckBoxFlagsBehaviour), new UIPropertyMetadata(null, ValueChanged));
private static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
isValueChanging = true;
byte mask = Convert.ToByte(GetMask(d));
byte value = Convert.ToByte(e.NewValue);
BindingExpression exp = BindingOperations.GetBindingExpression(d, IsCheckedProperty);
object dataItem = GetUnderlyingDataItem(exp.DataItem);
PropertyInfo pi = dataItem.GetType().GetProperty(exp.ParentBinding.Path.Path);
pi.SetValue(dataItem, (value & mask) != 0, null);
((CheckBox)d).IsChecked = (value & mask) != 0;
isValueChanging = false;
} // end ValueChanged
public static bool? GetIsChecked(DependencyObject obj)
{
return (bool?)obj.GetValue(IsCheckedProperty);
} // end GetIsChecked
public static void SetIsChecked(DependencyObject obj, bool? value)
{
obj.SetValue(IsCheckedProperty, value);
} // end SetIsChecked
public static readonly DependencyProperty IsCheckedProperty =
DependencyProperty.RegisterAttached("IsChecked", typeof(bool?),
typeof(CheckBoxFlagsBehaviour), new UIPropertyMetadata(false, IsCheckedChanged));
private static void IsCheckedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (isValueChanging) return;
bool? isChecked = (bool?)e.NewValue;
if (isChecked != null)
{
BindingExpression exp = BindingOperations.GetBindingExpression(d, ValueProperty);
object dataItem = GetUnderlyingDataItem(exp.DataItem);
PropertyInfo pi = dataItem.GetType().GetProperty(exp.ParentBinding.Path.Path);
byte mask = Convert.ToByte(GetMask(d));
byte value = Convert.ToByte(pi.GetValue(dataItem, null));
if (isChecked.Value)
{
if ((value & mask) == 0)
{
value = (byte)(value + mask);
}
}
else
{
if ((value & mask) != 0)
{
value = (byte)(value - mask);
}
}
pi.SetValue(dataItem, value, null);
}
} // end IsCheckedChanged
///
/// Gets the underlying data item from an object.
///
/// The object to examine.
/// The underlying data item if appropriate, or the object passed in.
private static object GetUnderlyingDataItem(object o)
{
return o is DataRowView ? ((DataRowView)o).Row : o;
} // end GetUnderlyingDataItem
} // end class CheckBoxFlagsBehaviour
Öneri Paul için teşekkürler, ancak birden fazla onay kutusu varsa, bunlardan herhangi birinden ConvertBack geçersiz kılacak ve diğer bitlerin verilerini kaybedecektir. Bunu zor bir sorun haline getiren ConvertBack parçasıdır. –
Gerçekten de, örnek biraz basittir; Ancak, bu çözüm gelen boole bakabileceğinden hala geçerli olduğunu düşünüyorum? değer ve sonra^= DönüştürücüParametre'de sağlanan maskeye dayalı değer; mantıklı olmak? Eğer lemme bilmiyorsanız ve tatillerde biraz zaman geçirdiğimde bazı kodları yayınlayacağım. – PaulJ
Yayını, ConvertBack senaryosunu içerecek şekilde güncelledim, ayrıca uygulamanın çalışan bir kopyasına bir link gönderdiğimi de unutmayın. – PaulJ