जो एक अच्छा WPF बाइंडिंग चुनौती की तरह उन लोगों के लिए:आप कैसे एक तरफ झुकाव के एक अलग बिट के लिए एक चेकबॉक्स बांध सकते हैं?
मैं दो तरह से एक झंडे गणना (धन्यवाद इयान ओक्स, original MSDN post) के एक व्यक्ति बिट के लिए एक चेकबॉक्स बंधन के एक लगभग कार्यात्मक उदाहरण है। समस्या यह है कि बाध्यकारी व्यवहार करता है जैसे कि यह एक तरीका है (डेटा कॉन्टेक्स्ट के लिए यूआई, इसके विपरीत नहीं)। तो प्रभावी रूप से चेक बॉक्स प्रारंभ नहीं होता है, लेकिन अगर यह डेटा स्रोत को टॉगल किया गया है तो सही ढंग से अपडेट किया गया है। अटैचमेंट बिट-आधारित बाइंडिंग को सक्षम करने के लिए कुछ संलग्न निर्भरता गुणों को परिभाषित करने वाला वर्ग है। मैंने जो देखा है वह है कि ValueChanged कभी नहीं कहा जाता है, भले ही मैं DataContext को बदलने के लिए मजबूर करता हूं।
मैं क्या कोशिश की है: संपत्ति परिभाषा के आदेश को बदलने से स्पष्ट रूप से बाध्यकारी मोड = TwoWay की स्थापना की पुष्टि करने के DataContext अद्यतन, किसी भी प्रशंसनीय FrameworkMetadataPropertyOptions (AffectsRender, BindsTwoWayByDefault), बाहर बुदबुदाती है एक लेबल और पाठ बॉक्स का उपयोग करना,, बीटिंग दीवार पर सिर, संघर्ष के मामले में EnumValueProperty करने के लिए ValueProperty बदलना।
किसी भी सुझाव या विचारों की अत्यधिक सराहना की जाएगी, जो भी आप पेशकश कर सकते हैं उसके लिए धन्यवाद!
गणन:
[Flags]
public enum Department : byte
{
None = 0x00,
A = 0x01,
B = 0x02,
C = 0x04,
D = 0x08
} // end enum Department
XAML उपयोग:
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}"
वर्ग:
///
/// 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
सुझाव पॉल के लिए धन्यवाद, लेकिन यदि कई चेक बॉक्स हैं तो उनमें से किसी एक से कनवर्टबैक ओवरराइड करेगा और अन्य बिट्स के लिए डेटा खो देगा। यह कनवर्टबैक हिस्सा है जो इसे एक मुश्किल समस्या बनाता है। –
दरअसल, नमूना थोड़ा सा सरल है; हालांकि, मुझे लगता है कि यह समाधान अभी भी लागू होता है क्योंकि आप आने वाले बूल को देख सकते हैं? मूल्य और फिर^= कनवर्टर पैरामीटर में आपूर्ति किए गए मास्क पर आधारित मान; सही बात? यदि lemme नहीं पता है और छुट्टियों पर मुझे कुछ समय मिलता है तो मैं कुछ कोड पोस्ट करूंगा। – PaulJ
कनवर्टबैक परिदृश्य को शामिल करने के लिए पोस्ट को अपडेट किया गया, यह भी ध्यान दें कि मैंने एप्लिकेशन की एक कार्यशील प्रतिलिपि के लिए एक लिंक पोस्ट किया है। – PaulJ