I have attached behavior with 2 properties. Here is what I am trying to do, for this question details are optional.
First one is used to enable/disable behavior:
public static bool GetEnableHasErrors(DependencyObject obj) => (bool)obj.GetValue(EnableHasErrorsProperty);
public static void SetEnableHasErrors(DependencyObject obj, bool value) => obj.SetValue(EnableHasErrorsProperty, value);
public static readonly DependencyProperty EnableHasErrorsProperty =
DependencyProperty.RegisterAttached("EnableHasErrors", typeof(bool), typeof(Behaviors), new PropertyMetadata((d, e) =>
{
var element = d as FrameworkElement;
if (element == null)
throw new ArgumentException("Only used with FrameworkElement");
var handler = new RoutedEventHandler((s, a) => { ... }); // logic to set value of HasErrorsProperty attached property on element
if ((bool)e.NewValue)
element.SomeRoutedEvent += handler;
else
element.SomeRoutedEvent -= handler;
}));
Second one is used to pass the result out:
public static bool GetHasErrors(DependencyObject obj) => (bool)obj.GetValue(HasErrorsProperty);
public static void SetHasErrors(DependencyObject obj, bool value) => obj.SetValue(HasErrorsProperty, value);
public static readonly DependencyProperty HasErrorsProperty =
DependencyProperty.RegisterAttached("HasErrors", typeof(bool), typeof(Behaviors));
And this result can go into view model via normal binding or used in the view, whatever:
<Grid local:Behaviors.EnableHasErrors="True"
local:Behaviors.HasErrors="{Binding HasErrors, Mode=OneWayToSource}" >
It feels wrong what I need 2 dependency properties for this. Is it possible to use just one? Couldn't I somehow infer inside behavior what I have logic enabled by having binding set? Isn't that enough?
I tried to use single property of BindingBase type, failed, found my own question and this duplicate with not safisfying answer, so BindingBase feels wrong to me.
Ideas?
I don't know of any way to avoid this for your specific case.
For more complex behaviors like this, it can be useful to use an attached behavior. Attached behaviors have methods which are called when the behavior is attached or detached, which you can use to subscribe to / unsubscribe from events. These are however significantly more verbose to use.
For example:
Usage would then be something like:
These used to be available only if you specifically installed the "Blend for Visual Studio SDK for .NET" component (Visual Studio 2017), but are now available in the Microsoft.Behaviors.Xaml.Wpf NuGet package.
If you've got a two-way binding which takes a more complex type than
bool(such asobject), there is a trick you can do:This uses a sentinel initial value of
initialBindingTarget, and checks to see when the binding changes the value away from this.