algorytmus
algorytmus

Reputation: 973

Invoke WPF Setter manually

I would like to call a Setter (WPF specific) passed in a code behind.

void Invoke(Setter setter)
{
   //I am interested what to do here, ?
}

the setter will be something like

<Setter TargetName="SomeUiElement" Property="SomeProperty" Value="{Binding SomeValue}" />

//resolution similar to
void Call(Setter setter)
{
   setter.Property.SetValue(setter.TargetObject, setter.Value.GetValue())
}

Thanks in advance. Please be specific.

Upvotes: 0

Views: 725

Answers (1)

Ian Griffiths
Ian Griffiths

Reputation: 14547

Setters are not quite what they seem. When WPF activates them, they don't strictly set a property's value (despite the name). Instead, they contribute a possible value, which may or may not have an effect on the property's effective value. (It depends on whether a higher priority property value source is currently active. http://msdn.microsoft.com/en-us/library/ms743230.aspx documents 11 different places property values can come from.) And when setters deactivate, they no longer offer that value.

The reason I mention this is to explain why a setter is never really "invoked". Invocation is instantaneous - it's a thing that happens at a particular moment. Setters, on the other hand, are active for some duration. (So there are two interesting instants: the point at which they become active, and the point at which they cease to be active.)

So if you're asking how to invoke a setter, you may not have the right tool for whatever job you're trying to do. The closest that can happen is that the setter becomes active, and remains active for however long you want it to.

Moreover, activation of a setter doesn't guarantee that its target property will actually change, because there may be other, higher priority value sources. Moreover, for it to be clear even what activation should mean, you need to know the way in which the setter is being used - the setters in the default style have a lower predence than those in a style defined by the application, which in turn have a lower priority than setters activated by a trigger in a template...

So a setter in isolation is meaningless, because its behaviour (i.e., what it does when it becomes active) is defined by the context in which the setter appears.

Now from your code, it looks like what you really want to do is arrange for the Local Value of the setter's target to be set to whatever value the property would acquire if a) the setter became active and b) that setter was the highest priority value available for that property. But that's not something a setter actually knows how to do.

Yes, it's ironic, but setters don't actually know how to set properties.

The code that causes the setter's value to become the target property value is actually distributed across various parts of WPF (including the Trigger and Style classes, amongst others). There isn't a straightforward way of getting WPF to do what you want, because it doesn't have a way of doing it in isolation - WPF's own processing of setters is mixed in with many other aspects of the property system. I'd strongly recommend trying to find some other way to solve whatever problem you were hoping to solve this way.

Upvotes: 6

Related Questions