WPF Custom Button Control Command Not Firing - wpf

I created an override of a button:
public class LauncherButton : Button
{
public ImageSource ImageSource
{
get { return (ImageSource)GetValue(ImageSourceProperty); }
set { SetValue(ImageSourceProperty, value); }
}
public static readonly DependencyProperty ImageSourceProperty =
DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(LauncherButton), new UIPropertyMetadata(null));
public string Caption
{
get { return (string)GetValue(CaptionProperty); }
set { SetValue(CaptionProperty, value); }
}
public static readonly DependencyProperty CaptionProperty =
DependencyProperty.Register("Caption", typeof(string), typeof(LauncherButton), new UIPropertyMetadata(null));
public ICommand ExecuteCommand
{
get { return (ICommand)GetValue(ExecuteCommandProperty); }
set { SetValue(ExecuteCommandProperty, value); }
}
public static readonly DependencyProperty ExecuteCommandProperty
= DependencyProperty.Register("ExecuteCommand", typeof(ICommand), typeof(LauncherButton));
}
I use it here:
<controls:LauncherButton Caption="Job Phases"
ImageSource="/FMG.UI.WPF.Shared;component/Media/Images/jobphase_128.png"
Margin="10"
Style="{StaticResource TabletLauncherButtonStyle}"
ExecuteCommand="{Binding ItemSelectedCommand}"
CommandParameter="{x:Static enums:View.JobPhases}"/>
and the view's VM:
public class TabletHomeViewModel : _HomeViewBase
{
private ICommand _ItemSelectedCommand;
public ICommand ItemSelectedCommand
{
get
{
if (_ItemSelectedCommand == null)
_ItemSelectedCommand = new RelayCommand(p => itemSelecteExecuted((View)p), p => itemSelecteCanExecute((View)p));
return _ItemSelectedCommand;
}
}
private bool itemSelecteCanExecute(View view)
{
return true;
}
private void itemSelecteExecuted(View view)
{
}
}
The ItemSelectedCommand's Getter fires on startup, but when I click on the button, the command doesn't fire. The Output Window doesn't show any binding problems.
If I wire up a click event for it, that does fire.
Anyone see what's wrong?
Thanks

Related

How to bind a RelayCommand(MVVM) to a RoutedCommand? (CommandBinding)

I want to create a custom class of a CommandBinding, where a RelayCommand of my ViewModel is executed when the RoutedCommand is executed.
Currently there is only the possibility to create CommandBindings which have Executed methods in the codebehind class.
Example:
<CommandBinding Command="ApplicationCommands.Close" Executed="CloseCommandHandler"
CanExecute="CanExecuteHandler"/>
This needs the CloseCommandHandler methode in the code behind.
I would want to write the following.
<CommandBinding RoutedCommand="ApplicationCommands.Close" Command={Binding Path=CloseCommand}/>
The only problem is that i can't find the bubble down and up event of the RoutedCommands.
There is no
OnPreviewCommand(object command, object commandParammeter)
OnCommand(object command, object commandParammeter)
Where is the RoutedCommand bubble down and up handled?
I came up with a solutions of my own. Its not the most beautiful, but its working.
I derived from the ContentControl. The new Control has a RoutedCommandBindings property, which contains a list of "sort of" CommandBindings between RoutedCommands and RelayCommands.
It can be used like this.
<CSControls:RoutedCommandBinder>
<CSControls:RoutedCommandBinder.RoutedCommandBindings>
<CSControls:RoutedCommandBindingCollection>
<CSControls:RoutedCommandBinding RoutedCommand="{x:Static ApplicationCommands.New}" Command="{Binding Path=AddInstanceCommand}"/>
</CSControls:RoutedCommandBindingCollection>
</CSControls:RoutedCommandBinder.RoutedCommandBindings>
<CSControls:RoutedCommandBinder.Content>
<!-- Every RoutedCommand of type ApplicationCommands.New will execute the binded RelayCommand "AddInstanceCommand-->
</CSControls:RoutedCommandBinder.Content>
</CSControls:RoutedCommandBinder>
Here is the CustomControl code.
public class RoutedCommandBinder : ContentControl
{
public RoutedCommandBinder()
{
this.DataContextChanged += RoutedCommandBinder_DataContextChanged;
}
public static readonly DependencyProperty RoutedCommandBindingsProperty = DependencyProperty.Register("RoutedCommandBindings", typeof(RoutedCommandBindingCollection), typeof(RoutedCommandBinder), new PropertyMetadata(new RoutedCommandBindingCollection(), OnRoutedCommandBindingsChanged));
public RoutedCommandBindingCollection RoutedCommandBindings
{
get { return (RoutedCommandBindingCollection)this.GetValue(RoutedCommandBindingsProperty); }
set { SetValue(RoutedCommandBindingsProperty, value); }
}
private static void OnRoutedCommandBindingsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
RoutedCommandBinder binder = (RoutedCommandBinder)d;
binder.CommandBindings.Clear();
SetDataContextForCommandBindings(binder);
if (e.NewValue != null)
{
RoutedCommandBindingCollection bindings = (RoutedCommandBindingCollection)e.NewValue;
foreach (RoutedCommandBinding binding in bindings)
{
binder.CommandBindings.Add(new CommandBinding(binding.RoutedCommand, binder.RoutedCommandExecuted, binder.CanExecuteRoutedEventHandler));
}
}
}
private void RoutedCommandBinder_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
SetDataContextForCommandBindings(this);
}
private static void SetDataContextForCommandBindings(RoutedCommandBinder binder)
{
if (binder.DataContext != null && binder.RoutedCommandBindings != null)
{
foreach (RoutedCommandBinding binding in binder.RoutedCommandBindings)
{
binding.DataContext = binder.DataContext;
}
}
}
private void RoutedCommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
RoutedCommandBinding binding = this.RoutedCommandBindings.FirstOrDefault(t => t.RoutedCommand == e.Command);
if (binding != null)
{
binding.Command.Execute(e.Parameter);
}
}
private void CanExecuteRoutedEventHandler(object sender, CanExecuteRoutedEventArgs e)
{
RoutedCommandBinding binding = this.RoutedCommandBindings.FirstOrDefault(t => t.RoutedCommand == e.Command);
if (binding != null)
{
e.CanExecute = binding.Command.CanExecute(e.Parameter);
}
}
}
public class RoutedCommandBindingCollection : List<RoutedCommandBinding>
{
}
public class RoutedCommandBinding : FrameworkElement
{
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(RoutedCommandBinding), new PropertyMetadata(null));
public ICommand Command
{
get { return (ICommand)this.GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public static readonly DependencyProperty RoutedCommandProperty = DependencyProperty.Register("RoutedCommand", typeof(RoutedCommand), typeof(RoutedCommandBinding), new PropertyMetadata(null));
public RoutedCommand RoutedCommand
{
get { return (RoutedCommand)this.GetValue(RoutedCommandProperty); }
set { SetValue(RoutedCommandProperty, value); }
}
}

How to catch a property changed event after binding

I have a custom UserControl:
public partial class CustomCtrl : UserControl
{
public CustomCtrl()
{
InitializeComponent();
}
public string Prova
{
get { return (string)GetValue(ProvaProperty); }
set
{
SetValue(ProvaProperty, value);
}
}
public static readonly DependencyProperty ProvaProperty =
DependencyProperty.Register("Prova", typeof(string), typeof(CustomCtrl));
}
I do this simple binding:
CustomCtrl c = new CustomCtrl();
TextBlock t = new TextBlock();
c.SetBinding(CustomCtrl.ProvaProperty, new Binding("Text") { Source = t });
t.Text = "new string";
Now c.Prova is "new string", but how can I catch in my CustomControl class the event informing me that Prova has changed?
Something like this (this will catch changes on all instances of CustomCtrl):
public static readonly DependencyProperty ProvaProperty =
DependencyProperty.Register(
"Prova",
typeof(string),
typeof(CustomCtrl),
new PropertyMetadata( new PropertyChangedCallback(OnValueChanged) )
);
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// This is called whenever the Prova property has been changed.
}
If "clients" of your CustomCtrl wanted to catch a change to that property for a specific instance then they could use:
CustomCtrl instanceofsomecustomctrl = .......
DependencyPropertyDescriptor descr =
DependencyPropertyDescriptor.FromProperty(CustomCtrl.ProvaProperty, typeof(CustomCtrl));
if (descr != null)
{
descr.AddValueChanged(instanceofsomecustomctrl, delegate
{
// do something because property changed...
});
}
I think this is what you're looking for, you want an event onChangeHandler.
public partial class CustomCtrl : UserControl
{
public CustomCtrl()
{
InitializeComponent();
}
public string Prova
{
get { return (string)GetValue(ProvaProperty); }
set
{
SetValue(ProvaProperty, value);
OnPropertyChanged("Prova");
}
}
protected void OnPropertyChanged(string prova)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(prova));
}
}
//This portion could go in the class where the event takes place
private delegate void UpdateDelegate(DependencyProperty dp, Object value);
}

Binding BindableApplicationBarIconButton IsEnabled property to Relaycommand CanExecute Windows Phone 7.1

I am using Phone7.Fx R1
The following works. The system does not react when a user presses the button. This means, than there is no reaction if Stop Game is pressed without a game has been started and vice versa.
However the button looks active. I am aware that I can bind the IsEnabled to a different property, but I would like it to bind to NewGameCanExecute and StopGameCanExecute. Is this possible?
Some XAML code:
<Preview:BindableApplicationBarIconButton Command="{Binding NewGame}" IconUri="/images/icons/appbar.add.rest.png" Text="New game" />
<Preview:BindableApplicationBarIconButton Command="{Binding StopGame}" IconUri="/images/icons/appbar.stop.rest.png" Text="Stop game" />
And the relay commands:
public RelayCommand NewGame { get; private set; }
public RelayCommand StopGame { get; private set; }
//Constructor
NewGame = new RelayCommand(NewGameExecute, NewGameCanExecute);
StopGame = new RelayCommand(StopGameExecute, StopGameCanExecute);
void NewGameExecute()
{
_gameStarted = true;
_gameControlModel.StartNewGame();
StopGame.RaiseCanExecuteChanged();
}
bool NewGameCanExecute()
{
return !_gameStarted;
}
void StopGameExecute()
{
_gameControlModel.StopGame();
_gameStarted = false;
NewGame.RaiseCanExecuteChanged();
}
bool StopGameCanExecute()
{
return _gameStarted;
}
Couple of questions and answers:
Q: Have you tried to set a breakpoint in the CanExecute functions to see if it gets called?
A: Yes. It does get called, but the icon is not grayed out, eventhough false is returned.
The Execute method is not executed, if the CanExecute method returns false. But I want the icon to be grayed out like a normal button.
SOLUTION
I spend some time and came up with a solution, which can be found here:
http://pastebin.com/MM75xACj
This is obviously a bug in whatever BindableApplicationBarIconButton implementation you're using.
Ask the author of it for help, or debug your 3rd party software yourself.
SOLUTION
I spend some time and came up with a solution and edited the applicationbariconbutton class.
namespace Phone7.Fx.Controls
{
public class BindableApplicationBarIconButton : FrameworkElement, IApplicationBarIconButton
{
public int Index { get; set; }
public static DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(BindableApplicationBarIconButton), new PropertyMetadata(null, OnCommandPropertyChanged));
private static void OnCommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != e.OldValue)
{
((BindableApplicationBarIconButton)d).Command = (ICommand)e.NewValue;
}
}
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set {
Command.CanExecuteChanged -= ValueOnCanExecuteChanged;
SetValue(CommandProperty, value);
Command.CanExecuteChanged += ValueOnCanExecuteChanged;
}
}
private void ValueOnCanExecuteChanged(object sender, EventArgs eventArgs)
{
ICommand commandSender = sender as ICommand;
if(commandSender != null)
{IsEnabled = commandSender.CanExecute(null);}
}
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.RegisterAttached("CommandParameter", typeof(object), typeof(BindableApplicationBarIconButton), new PropertyMetadata(null, OnCommandParameterPropertyChanged));
private static void OnCommandParameterPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var invokeCommand = d as BindableApplicationBarIconButton;
if (invokeCommand != null)
{
invokeCommand.SetValue(CommandParameterProperty, e.NewValue);
}
}
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set
{
SetValue(CommandParameterProperty, value);
}
}
public static readonly DependencyProperty CommandParameterValueProperty =
DependencyProperty.RegisterAttached("CommandParameterValue", typeof(object), typeof(BindableApplicationBarIconButton), null);
public object CommandParameterValue
{
get
{
var returnValue = GetValue(CommandParameterValueProperty);
return returnValue;
}
set { SetValue(CommandParameterValueProperty, value); }
}
public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(BindableApplicationBarIconButton), new PropertyMetadata(true, OnEnabledChanged));
private static void OnEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != e.OldValue)
{
((BindableApplicationBarIconButton)d).Button.IsEnabled = (bool)e.NewValue;
}
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.RegisterAttached("Text", typeof(string), typeof(BindableApplicationBarIconButton), new PropertyMetadata(OnTextChanged));
public new static readonly DependencyProperty VisibilityProperty =
DependencyProperty.RegisterAttached("Visibility", typeof(Visibility), typeof(BindableApplicationBarIconButton), new PropertyMetadata(OnVisibilityChanged));
private static void OnVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != e.OldValue)
{
var button = ((BindableApplicationBarIconButton)d);
BindableApplicationBar bar = button.Parent as BindableApplicationBar;
bar.Invalidate();
}
}
public new Visibility Visibility
{
get { return (Visibility)GetValue(VisibilityProperty); }
set { SetValue(VisibilityProperty, value); }
}
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != e.OldValue)
{
((BindableApplicationBarIconButton)d).Button.Text = e.NewValue.ToString();
}
}
public ApplicationBarIconButton Button { get; set; }
public BindableApplicationBarIconButton()
{
Button = new ApplicationBarIconButton();
Button.Text = "Text";
Button.Click += ApplicationBarIconButtonClick;
}
void ApplicationBarIconButtonClick(object sender, EventArgs e)
{
if (Command != null && CommandParameter != null)
Command.Execute(CommandParameter);
else if (Command != null)
Command.Execute(CommandParameterValue);
if (Click != null)
Click(this, e);
}
public bool IsEnabled
{
get { return (bool)GetValue(IsEnabledProperty); }
set { SetValue(IsEnabledProperty, value); }
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public event EventHandler Click;
public Uri IconUri
{
get { return Button.IconUri; }
set { Button.IconUri = value; }
}
}

WPF Binding Expression and Dependency property

I am trying to bind a text box to a dependency property to change its width. The following code is not working. Any help?
public class ToolbarManager : DependencyObject
{
public static readonly DependencyProperty toolbarButtonWidth = DependencyProperty.Register("toolbarButtonWidth", typeof(Double), typeof(ToolbarManager), new FrameworkPropertyMetadata(32.0, FrameworkPropertyMetadataOptions.AffectsMeasure ));
public static readonly DependencyProperty toolbarButtonHeight = DependencyProperty.Register("toolbarButtonHeight", typeof(Double), typeof(ToolbarManager), new FrameworkPropertyMetadata(32.0, FrameworkPropertyMetadataOptions.AffectsMeasure));
public double ButtonWidth
{
get { return (double)GetValue(toolbarButtonWidth); }
set { SetValue(toolbarButtonWidth, value); }
}
public double ButtonHeight
{
get { return (double)GetValue(toolbarButtonHeight); }
set { SetValue(toolbarButtonHeight, value); }
}
public static ToolbarManager Instance { get; private set; }
static ToolbarManager()
{
Instance = new ToolbarManager();
}
}
Here is the markup code:
<TextBox Width="{Binding Source={x:Static local:ToolbarManager.Instance}, Path=ButtonWidth, Mode=OneWay}" />
The default value works, but if I modify the value in code nothing happens ?!!!
rename your dependency property should solve your problem
public class ToolbarManager : DependencyObject
{
public static readonly DependencyProperty ButtonWidthProperty =
DependencyProperty.Register("ButtonWidth", typeof(Double), typeof(ToolbarManager), new FrameworkPropertyMetadata(32.0, FrameworkPropertyMetadataOptions.AffectsMeasure ));
public static readonly DependencyProperty ButtonHeightProperty =
DependencyProperty.Register("ButtonHeight", typeof(Double), typeof(ToolbarManager), new FrameworkPropertyMetadata(32.0, FrameworkPropertyMetadataOptions.AffectsMeasure));
public double ButtonWidth
{
get { return (double)GetValue(ButtonWidthProperty); }
set { SetValue(ButtonWidthProperty, value); }
}
public double ButtonHeight
{
get { return (double)GetValue(ButtonHeightProperty); }
set { SetValue(ButtonHeightProperty, value); }
}
public static ToolbarManager Instance { get; private set; }
static ToolbarManager()
{
Instance = new ToolbarManager();
}
}
hope this helps

DependencyProperty and WPF Designer

class MyLine : Shape {
public static readonly DependencyProperty X11Property;
public static readonly DependencyProperty X22Property;
public static readonly DependencyProperty Y11Property;
public static readonly DependencyProperty Y22Property;
static MyLine() {
X11Property = DependencyProperty.Register("X11", typeof(double), typeof(MyLine), new UIPropertyMetadata(double.NaN));
X22Property = DependencyProperty.Register("X22", typeof(double), typeof(MyLine), new UIPropertyMetadata(double.NaN));
Y11Property = DependencyProperty.Register("Y11", typeof(double), typeof(MyLine), new UIPropertyMetadata(double.NaN));
Y22Property = DependencyProperty.Register("Y22", typeof(double), typeof(MyLine), new UIPropertyMetadata(double.NaN));
}
[TypeConverter(typeof(LengthConverter))]
public double X11 { get { return (double)GetValue(X11Property); } set { SetValue(X11Property, value); } }
[TypeConverter(typeof(LengthConverter))]
public double X22 { get { return (double)GetValue(X22Property); } set { SetValue(X22Property, value); } }
[TypeConverter(typeof(LengthConverter))]
public double Y11 { get { return (double)GetValue(Y11Property); } set { SetValue(Y11Property, value); } }
[TypeConverter(typeof(LengthConverter))]
public double Y22 { get { return (double)GetValue(Y22Property); } set { SetValue(Y22Property, value); } }
protected override System.Windows.Media.Geometry DefiningGeometry {
get {
var geometryGroup = new GeometryGroup();
// Add line
geometryGroup.Children.Add(new LineGeometry(new Point(X11, Y11), new Point(X22, Y22)));
return geometryGroup;
}
}
}
Why when I update the "myLine" coordinates in WPF designer(VS 2010), it does not update it automatically(live)?
When using default "Line" WPF objects, they are automatically updated when the XAML code is changed(edited) in XAML/Design view.
Since these properties affect rendering, you should specify it in the metadata:
X11Property = DependencyProperty.Register("X11", typeof(double), typeof(DirectionLine), new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsRender));
I'm not sure it will be enough for the designer to take it into account, but it's worth a try...

Resources