wpf MVVM Focus cursor on textbox - c#

In a WPF window, I'm trying to put the cursor by default on one of the textboxes.
After reading some questions and answers, I tried the following:
xaml:
<StackPanel Grid.Row="1"
<StackPanel.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding UserShouldEditValueNow}" Value="true">
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=FID}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<TextBox Name ="FID" Text="{Binding FixID, UpdateSourceTrigger=PropertyChanged}"
FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"/>
</StackPanel>
cs: (Viewmodel)
this.UserShouldEditValueNow = true;
I expected to see a blinking cursor on the textbox FID when opening the window.
However, there's no cursor at all on this textbox.
Debugging showed me that I'm going through the cs code, setting the value to true.
any ideas why?

Solution involves:
1. Adding a FocusExtension class.
2. Focus and Keyboard.Focus are inside Dispatcher.BeginInvoke
cs.
public static class FocusExtension
{
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(FocusExtension),
new UIPropertyMetadata(false, OnIsFocusedPropertyChanged));
private static void OnIsFocusedPropertyChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var uie = (UIElement)d;
if ((bool)e.NewValue)
{
uie.Dispatcher.BeginInvoke(
new Action(
delegate{
uie.Focus();
Keyboard.Focus(uie);
}
)
);
}
}
}
.xaml
<TextBox Text="{Binding FixID, UpdateSourceTrigger=PropertyChanged}" viewModels:FocusExtension.IsFocused="{Binding UserShouldEditValueNow}" />

Related

An style for a tooltip only works partially

I would like to have an standar tooltip for all the controls, setting the initial delay, the show delay and that it can be shown when is not enabled. In the control I only would need to set the text of the tooltip in each case.
I have this style:
<sys:Int32 x:Key="TooltipInitialShowDelay">2000</sys:Int32>
<sys:Int32 x:Key="TooltipInitialShowDelayLong">5000</sys:Int32>
<sys:Int32 x:Key="TooltipDisplayTime">60000</sys:Int32>
<Style TargetType="ToolTip" x:Key="ToolTipDefaultStyle">
<Setter Property="ToolTipService.ShowOnDisabled" Value="true"/>
<Setter Property="ToolTipService.InitialShowDelay" Value="{StaticResource TooltipInitialShowDelay}"/>
<Setter Property="ToolTipService.ShowDuration" Value="{StaticResource TooltipDisplayTime}"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding PlacementTarget.(dp:ToolTipDependencyProperty.Texto), RelativeSource={RelativeSource AncestorType=ToolTip}}" MaxWidth="400" TextWrapping='Wrap' />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
I have this dependency properties:
public static class ToolTipDependencyProperty
{
#region Texto
public static readonly DependencyProperty TextoProperty =
DependencyProperty.RegisterAttached(
"Texto",
typeof(string),
typeof(ToolTipDependencyProperty));
public static string GetTexto(DependencyObject obj)
{
return (string)obj.GetValue(TextoProperty);
}
public static void SetTexto(DependencyObject obj, string value)
{
obj.SetValue(TextoProperty, value);
}
#endregion Texto
#region InitialShowDelay
public static readonly DependencyProperty InitialShowDelayProperty =
DependencyProperty.RegisterAttached(
"InitialShowDelay",
typeof(int),
typeof(ToolTipDependencyProperty));
public static int GetInitialShowDelay(DependencyObject obj)
{
return (int)obj.GetValue(InitialShowDelayProperty);
}
public static void SetInitialShowDelay(DependencyObject obj, int value)
{
obj.SetValue(InitialShowDelayProperty, value);
}
#endregion InitialShowDelay
#region ShowDuration
public static readonly DependencyProperty ShowDurationProperty =
DependencyProperty.RegisterAttached(
"ShowDuration",
typeof(int),
typeof(ToolTipDependencyProperty));
public static int GetShowDuration(DependencyObject obj)
{
return (int)obj.GetValue(ShowDurationProperty);
}
public static void SetShowDuration(DependencyObject obj, int value)
{
obj.SetValue(ShowDurationProperty, value);
}
#endregion ShowDuration
}
And this is my button:
<Button Name="btnBuscar" Content="Buscar" Command="{Binding BuscarCommand}"
IsEnabled="{Binding BuscarIsEnabled}"
dp:ToolTipDependencyProperty.Texto="{Binding BuscarToolTip}">
<Button.ToolTip>
<ToolTip Style="{StaticResource ToolTipDefaultStyle}"/>
</Button.ToolTip>
</Button>
The problem is that the text is ahown, but only when the button is enabled. And also the initial show delay and show duration is the standard duration, not the values that I want to use.
However, if in the control I set the ToolTip.Service variables, it works.
How could I set the duration in the style?
Thanks.
The ToolTipService attached properties need to be set on the element that owns the tooltip, not the tooltip itself.
You'll need to create a style for Button, or FrameworkElement.

WPF: Parent which would display a specific child depending on input value

As far as I understand, usual Visibility={Binding SomeValue, Converter={…}} still keeps node in visual and logical tree even if it’s invisible. But what if I want to remove it completely and at the same time keep syntax light?
Right now, I’ve made a class called Switch allowing me to do stuff like that:
<Switch Value="{Binding Status}">
<TextBlock Switch.When="{x:Static Status.NotFound}" Text="Not found" />
<Button Switch.When="{x:Static Status.ConnectionError}" Text="Connection error. Try again?" />
<Grid Switch.When="{x:Static Status.Loaded}">…</Grid>
</Switch>
Here is a source code of that Switch thing.
I like how it looks and works, but sometimes some errors occur. For instance, while removing visual child from its previous location, rarely, but System.InvalidOperationException: Cannot modify the logical children for this node at this time because a tree walk is in progress. might happen. Cases like this are solvable, but the whole thing with them makes me think I’m doing something very wrong. What could it be? Maybe the whole idea is just not compatible with WPF at all? Or maybe I’m just missing something (like that thing that I have to override IEnumerator LogicalChildren { get; } to make it work properly)?
I think the answer is probably that you're trying to reparent the child controls the right way. Bad idea! They're just arbitrary content; don't treat them as controls. The actual reparenting in my code is done by hidden ContentPresenter magic in the template. All our control class code does is just sling them around like potatoes.
Here's a working version of the control that shouldn't give you any backtalk. But note that I had trouble comparing boxed enum values to each other. I'm interested in how you solved that problem.
Switch.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
namespace SwitchTestProject
{
[ContentProperty("Items")]
public class Switch : Control
{
public Switch()
{
Items = new List<DependencyObject>();
}
static Switch()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Switch), new FrameworkPropertyMetadata(typeof(Switch)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
OnValueChanged(null);
}
#region Switch.When Attached Property
public static Object GetWhen(DependencyObject obj)
{
return (Object)obj.GetValue(WhenProperty);
}
public static void SetWhen(DependencyObject obj, Object value)
{
obj.SetValue(WhenProperty, value);
}
public static readonly DependencyProperty WhenProperty =
DependencyProperty.RegisterAttached("When", typeof(Object), typeof(Switch),
new PropertyMetadata(null));
#endregion Switch.When Attached Property
#region Content Property
public Object Content
{
get { return (Object)GetValue(ContentProperty); }
protected set { SetValue(ContentPropertyKey, value); }
}
internal static readonly DependencyPropertyKey ContentPropertyKey =
DependencyProperty.RegisterReadOnly(nameof(Content), typeof(Object), typeof(Switch),
new PropertyMetadata(null));
public static readonly DependencyProperty ContentProperty = ContentPropertyKey.DependencyProperty;
#endregion Content Property
#region Value Property
public Object Value
{
get { return (Object)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(nameof(Value), typeof(Object), typeof(Switch),
new FrameworkPropertyMetadata(null, Value_PropertyChanged));
protected static void Value_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as Switch).OnValueChanged(e.OldValue);
}
private void OnValueChanged(object oldValue)
{
if (Value is IComparable)
{
// Boxed value types have to be a special case.
// Unless I jumped to an unwarranted conclusion about == not working.
var icompval = Value as IComparable;
foreach (var item in Items)
{
var icompwhen = GetWhen(item) as IComparable;
if (icompwhen != null && icompval.CompareTo(icompwhen) == 0)
{
Content = item;
return;
}
}
}
else
{
Content = Items.FirstOrDefault(item => GetWhen(item) == Value);
}
}
#endregion Value Property
#region Items Property
public List<DependencyObject> Items
{
get { return (List<DependencyObject>)GetValue(ItemsProperty); }
protected set { SetValue(ItemsPropertyKey, value); }
}
internal static readonly DependencyPropertyKey ItemsPropertyKey =
DependencyProperty.RegisterReadOnly(nameof(Items), typeof(List<DependencyObject>), typeof(Switch),
new PropertyMetadata(null));
public static readonly DependencyProperty ItemsProperty = ItemsPropertyKey.DependencyProperty;
#endregion Items Property
}
}
App.xaml or Themes\Generic.xaml
You could do a lot more with styling the parent here.
<Style TargetType="local:Switch">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:Switch">
<ContentPresenter
/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Usage:
<local:Switch
Value="{Binding Status}"
>
<TextBlock
local:Switch.When="{x:Static local:Status.NotFound}"
>This is a test</TextBlock>
<TextBlock
local:Switch.When="{x:Static local:Status.ConnectionError}"
>There was an error in the connection</TextBlock>
</local:Switch>
Pure XAML alternative
The bug in your Switch control is probably fixable, but this will work reliably without any nonsense (other than all the verbosity).
<ContentControl>
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding Status}" Value="NotFound">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="Not found" />
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="ConnectionError">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Button Content="Connection error. Try again?" />
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="Loaded">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Ellipse
Height="32"
Width="32"
Fill="DeepSkyBlue"
/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
We set the content using DataTemplates rather than setting the Content property directly because if we use the latter method, only one instance of each child control will ever exist, so we wouldn't be able to factor the style out as a resource and reuse it.
And because templating is the canonical way to create new controls in XAML.

Get Treeviewitem from Menu Context. WPF XAML MVVM

Good day.
I have created a TreeViewHelper Class in order to trigger events and pass through datacontext to functions. However. Id like to select the treeviewitem when right clicking.
My solution follows the MVVM pattern as close as possible. So if possible i'd like to avoid the Trigger Event feature that is provided.
Id love for some advice on how to tackle this issue.
here is the treeviewhelper.cs class
public static class TreeViewHelper
{
#region SelectedItem
public static object GetSelectedItem(DependencyObject obj)
{
return (object)obj.GetValue(SelectedItemProperty);
}
public static void SetSelectedItem(DependencyObject obj, object value)
{
obj.SetValue(SelectedItemProperty, value);
}
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.RegisterAttached("SelectedItem", typeof(object), typeof(TreeViewHelper), new UIPropertyMetadata(null, SelectedItemChanged));
private static void SelectedItemChanged(DependencyObject obj, DependencyPropertyChangedEventArgs dpea)
{
if (!(obj is TreeView) || dpea.NewValue == null)
return;
var view = obj as TreeView;
view.SelectedItemChanged += (sender, e) => SetSelectedItem(view, e.NewValue);
var command = (ICommand)(view as DependencyObject).GetValue(SelectedItemChangedProperty);
if (command != null)
{
if (command.CanExecute(null))
command.Execute(new DependencyPropertyEventArgs(dpea));
}
}
#endregion
#region Selected Item Changed
public static ICommand GetSelectedItemChanged(DependencyObject obj)
{
return (ICommand)obj.GetValue(SelectedItemProperty);
}
public static void SetSelectedItemChanged(DependencyObject obj, ICommand value)
{
obj.SetValue(SelectedItemProperty, value);
}
public static readonly DependencyProperty SelectedItemChangedProperty =
DependencyProperty.RegisterAttached("SelectedItemChanged", typeof(ICommand), typeof(TreeViewHelper));
#endregion
#region Event Args
public class DependencyPropertyEventArgs : EventArgs
{
public DependencyPropertyChangedEventArgs DependencyPropertyChangedEventArgs { get; private set; }
public DependencyPropertyEventArgs(DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
this.DependencyPropertyChangedEventArgs = dependencyPropertyChangedEventArgs;
}
}
#endregion
}
Here is the XAML Code (shortened)
<TreeView x:Name="TestPlanTreeView"
ItemsSource="{Binding Data.TreeViewCollection}"
utils:TreeViewHelper.SelectedItem="{Binding CurrSelItem}"
utils:TreeViewHelper.SelectedItemChanged="{Binding SelItemChgCmd}">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsSelected" Value="{Binding IsSelected}"/>
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu ItemsSource="{Binding MenuCollection, RelativeSource={RelativeSource Self}}">
<ContextMenu.Resources>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding Command}" />
</Style>
</ContextMenu.Resources>
<ContextMenu.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Header}"/>
</HierarchicalDataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Nodes}">
<TextBlock Text="{Binding Header}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
This is how i trigger a function when selecting a new item.
SelItemChgCmd = new RelayCommand<DependencyPropertyEventArgs>(Data.TreeViewItemSelected);
CurrSelItem = new object();
public void TreeViewItemSelected(DependencyPropertyEventArgs dpe)
{
TreeViewItem selectedTreeViewItem = dpe.DependencyPropertyChangedEventArgs.NewValue as TreeViewItem;
ListViewCollection = BuildListViewCollection(selectedTreeViewItem);
}
What I would love to do, is to be able to select the treeviewitem before right clicking on the object. However, I am not sure how to do that with my given code without hacking it.
My original thoughts were to create a property in the treeviewhelper for PreviewRightMouseButtonUp and have that trigger the SelectedItem event, but i then run into issues with data.
Since the PreviewRightMouseButtonUp does not hold the same method types as the selectedItem Changed event, then i run into these data issues.
Id really appreciate some thoughts on this matter. Its been blocking me for a while now.

Update Normal Property in Dependency property/AttachedProperty,

I am trying to bind a normal property of AvalonDock,
xmlns:xcad="http://schemas.xceed.com/wpf/xaml/avalondock"
<xcad:LayoutAnchorable Title="Folder" CanHide="{Binding IsHideExplorerView}">
<Views:ExplorerView DataContext="{Binding ExplorerViewModel}"/>
</xcad:LayoutAnchorable>
Here CanHide is a Normal property, if trying to bind will throw the exception like
A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
My question is, Is it possible any way to make a normal property to override DependencyProperty to make it Bindable.
Edit
Added a class which inherit LayoutAnchorable but PropertyChangedCallback of DependencyProperty Never calls.
public class ExtendedAnchorableItem : LayoutAnchorable
{
public static readonly DependencyProperty IsCanHideProperty =
DependencyProperty.RegisterAttached("IsCanHide", typeof(bool), typeof(ExtendedAnchorableItem),
new FrameworkPropertyMetadata((bool)false,
new PropertyChangedCallback(OnCanHideChanged)));
public bool IsCanHide
{
get { return (bool)GetValue(IsCanHideProperty); }
set { SetValue(IsCanHideProperty, value);
this.IsVisible = value; // No effect.
}
}
private static void OnCanHideChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((ExtendedAnchorableItem)d).Hide();
}
}
XAML
<xcad:LayoutAnchorablePane>
<Utility:ExtendedAnchorableItem IsCanHide="{Binding IsHideExplorer}">
<Views:ExplorerView DataContext="{Binding ExplorerViewModel}"/>
</Utility:ExtendedAnchorableItem>
</xcad:LayoutAnchorablePane>
Similarly i have tried creating an AttachedProperty which can hook it to LayoutAnchorable but PropertyChangedCallback Never get called click here for a new question i have posted.
Any Help guys ?
I did and example previously in my case i need to create new button with 2 images one when the button is available and the other one when it's disabled, to do that first i created new user control named "MyButton" my xaml was like this
<Button ToolTip="{Binding ButtonLabel,RelativeSource={RelativeSource AncestorType=UserControl,Mode=FindAncestor},UpdateSourceTrigger=PropertyChanged}"
Command="{Binding ButtonCommand,RelativeSource={RelativeSource AncestorType=UserControl,Mode=FindAncestor},UpdateSourceTrigger=PropertyChanged}"
Cursor="Hand" VerticalAlignment="Center" >
<Button.Template>
<ControlTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="45"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Name="ButtonImage" IsEnabled="{Binding Path=IsEnabled,RelativeSource={RelativeSource AncestorType=Button,Mode=FindAncestor}}" >
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="Source" Value="{Binding ActiveImage,RelativeSource={RelativeSource AncestorType=UserControl,Mode=FindAncestor},UpdateSourceTrigger=PropertyChanged}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Source" Value="{Binding DeactiveImage,RelativeSource={RelativeSource AncestorType=UserControl,Mode=FindAncestor},UpdateSourceTrigger=PropertyChanged}"/>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<Label Name="LabelContent" Content="{Binding ButtonLabel,RelativeSource={RelativeSource AncestorType=UserControl,Mode=FindAncestor},UpdateSourceTrigger=PropertyChanged}"
Grid.Column="1" IsEnabled="{Binding Path=IsEnabled,RelativeSource={RelativeSource AncestorType=Button,Mode=FindAncestor}}" VerticalContentAlignment="Center" />
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
then i added dependency Properties for ActiveImage and DeactiveImage using this code
public static DependencyProperty activeImage =
DependencyProperty.Register("ActiveImage", typeof(type of this property like "string"), typeof(type of the custom control that you need like "MyButton"), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public string ActiveImage
{
get { return (string)GetValue(activeImage); }
set { SetValue(activeImage, value); }
}
then i used this new control in my project
<custom:MyButton ButtonCommand="{Binding DecreaseImagesCount}" ButtonLabel="ZoomIn" ActiveImage="/Images/ActiveImages/ZoomIn.png" DeactiveImage="/Images/GrayImages/ZoomIn.png"
Grid.Column="2" Margin="3,4" />
notice that i can do binding the path for Button Image now
If it is enough for you to just set that property from your view model then you could use an attached behavior.
Just create a new class and add an attached property like this (I did not really test this, since I actually do not have AvalonDock at hand, but you should get the idea):
public class YourBehavior
{
public static readonly DependencyProperty YourCanHideProperty = DependencyProperty.RegisterAttached(
"YourCanHide",
typeof(bool),
typeof(LayoutAnchorable),
new PropertyMetadata(YourCanHidePropertyChanged));
private static void YourCanHidePropertyChanged(
DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs e)
{
LayoutAnchorable control = dependencyObject as LayoutAnchorable;
if (control != null)
{
control.CanHide = e.NewValue as bool;
}
}
public static bool GetYourCanHideProperty(LayoutAnchorablewindow)
{
return window.GetValue(YourProperty) as bool?;
}
public static void SetYourCanHideProperty(LayoutAnchorable control, bool value)
{
window.SetValue(YourProperty, value);
}
}
Now you should be able to use that behavior like this:
<xcad:LayoutAnchorable Title="Folder" namespacealias:YourBehavior.YourCanHideProperty="{Binding IsHideExplorerView}"/>
If you want to have it working in both directions just check out the attached Blend behaviors.
Yes, you can do it.. you need to implement INotifypropertyChanged interface and raise a ProprtyChanged Event inside the property setter. After changing the property to a DependencyProperty, you will get the notification mechanism, so the property change is propagated to the target (in this case xcad) .
you can find lot of examples implementing the INotifyPropertyChanged..

Saving a WPF canvas as an image following MVVM Pattern

I have a canvas, e.g. similar to this solution or many others using the ItemsControl.
Now I want a button which should be bound to an ICommand. This command should call a method of ViewModel class which can save the image.
The saving method is clear, but how do I do the binding following the MVVM pattern?
You could pass the Canvas to the ViewModel's Save method using a CommandParameter
<Button Content="Save"
Command="{Binding SaveCanvasCommand}"
CommandParameter="{Binding ElenementName=myCanvas}" ?>
<Canvas x:Name="myCanvas">
<!-- Stuff to save -->
</Canvas>
And somewhere in you ViewModel or Command you'd have
void SaveCanvasCommandExecute(object parameter)
{
UIElement toSave = (UIElement)parameter;
//.. You'd probably use RenderTargetBitmap here to save toSave.
}
If you don't want to reference UI elements in your ViewModel you could use an attached behaviour:
internal static class Behaviours
{
public static readonly DependencyProperty SaveCanvasProperty =
DependencyProperty.RegisterAttached("SaveCanvas", typeof(bool), typeof(Behaviours),
new UIPropertyMetadata(false, OnSaveCanvas));
public static void SetSaveCanvas(DependencyObject obj, bool value)
{
obj.SetValue(SaveCanvasProperty, value);
}
public static bool GetSaveCanvas(DependencyObject obj)
{
return (bool)obj.GetValue(SaveCanvasProperty);
}
private static void OnSaveCanvas(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
// Save code.....
}
}
}
Then in your ViewModel you have your Command that sets a property, also on your ViewModel:
public ICommand SaveCanvasCommand
{
get
{
if (_saveCanvasCommand == null)
_saveCanvasCommand = new RelayCommand(() => { IsSaveCanvas = true; });
return _saveCanvasCommand;
}
}
And the property which is bound to your View:
public bool IsSaveCanvas
{
get { return _isSaveCanvas; }
set
{
_isSaveCanvas = value;
RaisePropertyChanged("IsSaveCanvas");
}
}
Then hooking it all up in the Xaml looks like this:
Add a Trigger on the Control that binds the value of your ViewModel property to your attached behaviour:
<UserControl.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsSaveCanvas}" Value="True">
<Setter Property="wpfApplication1:Behaviours.SaveCanvas" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsSaveCanvas}" Value="False">
<Setter Property="wpfApplication1:Behaviours.SaveCanvas" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Style>
And then bind your Button / MenuItem to the ViewModels Save Command:
<Canvas.ContextMenu>
<MenuItem Header="Save" Command="{Binding SaveCanvasCommand}"/>
</Canvas.ContextMenu>

Categories