Reputation: 22008
Let's see 2 examples:
For focus, we have to call method UIelement.Focus()
in code-behind, so standard approach in MVVM is to create *behaviour`:
public static class FocusedBehavior
{
public static bool GetIsFocused(DependencyObject obj)
{
return (bool)obj.GetValue(IsFocusedProperty);
}
public static void SetIsFocused(DependencyObject obj, bool value)
{
obj.SetValue(IsFocusedProperty, value);
}
public static readonly DependencyProperty IsFocusedProperty =
DependencyProperty.RegisterAttached("IsFocused", typeof(bool), typeof(FocusedBehavior), new UIPropertyMetadata(false, OnIsFocusedChanged));
private static void OnIsFocusedChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if((bool)e.NewValue)
(sender as UIElement).Focus();
}
}
Then for each control we want to be able to set focus we do
<Button ... local:FocusedBehavior.IsFocused="{Binding SomeDependencyProperty}"/>
where bool SomeDependencyProperty
has to be created in ViewModel for each control individually. This way ViewModel can change something in the View by setting value of its own property.
To set blur (see here), we have to change property BlurEffect.Radius
. This can be as simple as
<Window.Effect>
<BlurEffect Radius="{Binding SomeDependencyProperty}"/>
</Window.Effect>
where int SomeProperty
is again has to be created in ViewModel personally for each case.
Is there any more ways to change something in View by ViewModel?
I want to know all possibilities to be able to use the most appropriate. To set focus we have to use behaviour approach, to set blur simple binding. Are there more possibilities?
Very generic solution would be to let ViewModel know about View, so it can call methods and use properties when, to example, processing commands, but this is bad idea. Right? Though in this case View can be extended itself with public properties and methods to achieve some result (to example, set focus or set blur).
Upvotes: 1
Views: 1657
Reputation: 69985
Your question seems a little un-thought through... by changing a property in the view model, I can make just about anything happen in the view, through the use of IValueConverter
s, DataTrigger
s, Attached Properties, etc. For example, you don't need to use either a DependencyProperty
or an Attached Property to focus a UI element. You can do that with a plain bool
property in the view model and a DataTrigger
like this:
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding PropertyName}">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused}" Value="True">
<Setter Property="FocusManager.FocusedElement" Value="{Binding
RelativeSource={RelativeSource Self}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
So really, you seem to be asking what is possible in WPF and I don't think that that is a reasonably scoped (or on-topic) question to ask here. To find that out, you'd be better off reading through the Walkthrough: Getting Started with WPF page on MSDN.
However, I think that you might actually be asking How to change something in View by ViewModel [specifically when using MVVM]. In that case, I can think of another used element: the humble delegate
, which enables us to pass values between related view models, or in your case, from the view model to the view.
Using this mechanism, we can literally [indirectly] call UI methods in views from the view model, so as I said earlier... we can do just about anything - MVVM does not stop us from using anything that WPF provides.
Incidentally, why are you using DependencyProperty
s in your view model? You shouldn't have any declared in your view model, because they are for UI elements... in view models, you can just implement the INotifyPropertyChanged
interface and use plain old CLR properties with exactly the same functionality, but much less complexity.
UPDATE >>>
As mentioned, the DependencyProperty
is a UI class, meant for UI controls, such as a UserControl
. They are total overkill for use in view models, because as mentioned, we can use plain CLR properties there instead. If you look at the DependencyProperty
Class page on MSDN, you'll be able to see how many hundreds of public members that it has... why pay for all of these (in RAM) when you're not using any of them?
The INotifyPropertyChanged
interface doesn't add anything more than a DependencyProperty
, but instead offers the same property notification access, but for a greatly reduced cost (no hundreds of unused properties). I can tell by the way that you said that all of your view models extend the DependencyObject
class, that you have misunderstood the famous error below:
A
Binding
can only be set on aDependencyProperty
of aDependencyObject
I confess that it is a misleading error and does confuse new WPF users. So, my advice to you is for you to implement ordinary CLR type properties in your view model and to not extend the DependencyObject
class... you will then also be able to remove your UI related dll using
s. Furthermore, when using CLR properties, you will need to correctly implement the INotifyPropertyChanged
interface in order to 'plug them into' the WPF property change notification framework.
Now, you asked how to use delegate
s to pass data from the view model to the view... unfortunately, that is another whole question on its own and I have just about run out of time on this question. So instead of repeating the whole story again, I'd prefer to suggest that you read my answers to the Passing parameters between viewmodels and How to call functions in a main view model from other view models? questions here on Stack Overflow for explanations and code examples.
With all due respect, I'd appreciate it if you don't leave further comments asking for more information on this matter as this answer is really long enough now. If you do have any further questions, please ask a new question and provide as much code/information as possible.
Upvotes: 2