Pass unbound object as CommandParameter - c#

Is there a simple way to pass an object of type Color as CommandParameter in WPF?
I have a list of buttons which should change e.g. the background-color of my application.
The buttons would look like:
<Button Command={Binding SetBackgroundColor} CommandParameter={Color.Red} Background="Red" />
<Button Command={Binding SetBackgroundColor} CommandParameter={Color.Green} Background="Green" />
<Button Command={Binding SetBackgroundColor} CommandParameter={Color.White} Background="White" />
<Button Command={Binding SetBackgroundColor} CommandParameter={???} Background="#FF00FF" />
and on click on the colored button, the color should be changed.
Any ideas, patterns, best-practices, how-tos or workarounds for this?

You could write
<Button CommandParameter="{x:Static Colors.Red}" ... />
or
<Button ...>
<Button.CommandParameter>
<Color>#FF00FF</Color>
</Button.CommandParameter>
</Button>
or use a color resource:
<Window.Resources>
<Color x:Key="myColor">#FF00FF</Color>
...
</Window.Resources>
...
<Button CommandParameter="{StaticResource myColor}" ... />

Related

How can I reposition the content of a single cell in a WPF UniformGrid?

I am creating a keypad using a UniformGrid. The keypad has the usual 0-9 buttons, plus a 'Backspace' button. I want the 'Backspace' button to be smaller than the numeric buttons, and so I have applied a RenderTransform to it. All this works fine.
However, I additionally would like the 'Backspace' button to be repositioned (realigned) Right and Bottom within the UniformGrid cell, so that it is away from the numeric buttons.
Below is an image with the red arrow indicating where I would like to move the 'Backspace' button.
I have tried placing the 'Backspace' button inside a ContentControl and setting the HorizontalContentAlignment and VeriticalContentAlignment to Right and Down respectively, but this doesn't work.
Here is some sample XAML:
<UniformGrid Columns="3" Rows="4">
<Button Content="1" />
<Button Content="2" />
<Button Content="3" />
<Button Content="4" />
<Button Content="5" />
<Button Content="6" />
<Button Content="7" />
<Button Content="8" />
<Button Content="9" />
<Button />
<Button Content="0" />
<!--<ContentControl HorizontalContentAlignment="Right" VerticalContentAlignment ="Bottom">-->
<Button Content="X">
<Button.RenderTransform>
<ScaleTransform ScaleX=".75" ScaleY=".75" />
</Button.RenderTransform>
</Button>
<!--</ContentControl>-->
</UniformGrid>
Can this can be done?
Try RenderTransformOrigin
<Button Content="X" RenderTransformOrigin="1, 1">
<Button.RenderTransform>
<ScaleTransform ScaleX=".75" ScaleY=".75" />
</Button.RenderTransform>
</Button>
It should work, however I can't test right now.

Style all Buttons in a StackPanel the same way (UWP)

I want that all Buttons in a StackPanel have the same style.
Is there a similar possibility like in HTML / CSS?
For example, this makes in HTML the text of all buttons in the div with the class myBox blue:
CSS
.myBox Button{
color: blue;
}
HTML
<div class="myBox">
<button type="button">1</button>
<button type="button">2</button>
<button type="button">3</button>
</div>
When I have now this StackPanel, how can I make all Button text blue?
<StackPanel Orientation="Vertical" x:Name="ManagerMenu">
<Button x:Name="1" Content="1" />
<Button x:Name="2" Content="2" />
<Button x:Name="3" Content="3" />
</StackPanel>
You can do this by placing a default (= without an x:Key) Button style inside the stackpanel:
<StackPanel Orientation="Vertical" x:Name="ManagerMenu">
<StackPanel.Resources>
<Style TargetType="Button">
<Setter Property="Foreground" Value="Blue" />
...
</Style>
</StackPanel.Resources>
<Button x:Name="1" Content="1" />
<Button x:Name="2" Content="2" />
<Button x:Name="3" Content="3" />
</StackPanel>
But you may want to base it on a pre-existing style for buttons or it will look rather flat.
You can create a resource tag and then use this to multiple elements.
Take a look at this.
https://msdn.microsoft.com/en-us/windows/uwp/controls-and-patterns/styling-controls
If you want to use existing style and apply it to all buttons:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="Button" BasedOn="{StaticResource MyButtonStyle}"/>
</StackPanel.Resources>
<Button x:Name="1" Content="1" />
<Button x:Name="2" Content="2" />
<Button x:Name="3" Content="3" />
</StackPanel>

MaterialDesignXamlToolkit wpf dialoghost buttons are disabled when opened

I am using the MaterialDesignThemes nuget package along with the Mahapps.Metro package
I have this DialogHost
<material:DialogHost Name="PopupAddCustom" HorizontalAlignment="Center" VerticalAlignment="Center" IsOpen="False" >
<material:DialogHost.DialogContent>
<StackPanel Margin="16" Orientation="Vertical">
<Label Content="Add custom date" FontSize="16" />
<DatePicker />
<StackPanel Orientation="Horizontal">
<Button Content="ACCEPT" Style="{DynamicResource MaterialDesignFlatButton}" IsDefault="True" Margin="0,8,8,0" Command="material:DialogHost.CloseDialogCommand" CommandParameter="True" />
<Button Content="CANCEL" Style="{DynamicResource MaterialDesignFlatButton}" IsCancel="True" Margin="0,8,8,0" Command="material:DialogHost.CloseDialogCommand" CommandParameter="False" />
</StackPanel>
</StackPanel>
</material:DialogHost.DialogContent>
</material:DialogHost>
That is being openend by this button
<Button MinWidth="120" Margin="10" Style="{StaticResource MaterialDesignRaisedAccentButton}" ToolTip="Add in a new custom date." Command="{x:Static material:DialogHost.OpenDialogCommand}" CommandTarget="{Binding ElementName=PopupAddCustom}" >
<StackPanel Orientation="Horizontal">
<Rectangle Width="20" Height="20" Fill="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Foreground}">
<Rectangle.OpacityMask>
<VisualBrush Stretch="Fill" Visual="{StaticResource fa_plus}" />
</Rectangle.OpacityMask>
</Rectangle>
<TextBlock Margin="10,0,0,0" VerticalAlignment="Center" Text="Custom" />
</StackPanel>
</Button>
However when this dialog gets opened the ACCEPT and CANCEL buttons are disabled. So to check if anything was wrong I manually opened this dialog from the my MainWindow constructor like this
this.Loaded += delegate(object sender, RoutedEventArgs args)
{
this.PopupAddCustom.IsOpen = true;
};
When I open the dialog like this the button are in working order, am I missing something obvious here?
The problem was resolved by setting a command target for the buttons like this
CommandTarget="{Binding ElementName=PopupAddCustom}"
To save someone elses time: I had dialog content specified as command parameter and specifying CommandTarget did not help me.
What helps in my case, is to put CommandParameter before Command.
You can achieve that by passing content as resource.
Example:
Before:
<Button
...
Command="{x:Static material:DialogHost.OpenDialogCommand}"
>
<Button.CommandParameter>
<Grid>
** Dialog content **
</Grid>
</Button.CommandParameter>
** Button content **
</Button>
After:
<UserControl.Resources>
<Grid x:Key="MyDialogContent">
** Dialog content **
</Grid>
</UserControl.Resources>
<Button
...
CommandParameter="{StaticResource MyDialogContent}"
Command="{x:Static material:DialogHost.OpenDialogCommand}"
>
** Button content **
</Button>
And dialoghost buttons were not disabled anymore.

Matching size of controls in WPF

This is recurring problem I'm going into. How to match size of elements in WPF? Let's look at the following scenario:
<Grid>
<Popup>
<StackPanel>
<Button x:Name="btn1" />
<Button x:Name="btn2" />
<Button x:Name="btn3" />
</StackPanel>
</Popup>
<Border x:Name="border1">
Ala ma kota
</Border>
</Grid>
Now I'd like the btn1, btn2 and btn3 to be at least as wide as border1; contents of border changes dynamically, so no measuring and hardcoding is acceptable.
How can I achieve that?
Bind the buttons' Width property to the Border's Width property.
Something like:
<Button x:Name="btn1" Width="{Binding ElementName=border1, Path=Width}" />

click event of a button that contains more buttons, fires events wrong

I´m facing this problem:
I have a Button that works like a WrapPanel using the property "Template"
Template="{StaticResource WrapLikeTemplate}"
Where "WrapLikeTemplate is as follows:
<ControlTemplate x:Key="WrapLikeTemplate">
<WrapPanel Name="wpBody" Orientation="Horizontal" Margin="0,5,0,0">
<Button Content="{Binding XPath=./BUTTONS/Button[1]/Text}" Click="b1_Click" Height="55" Name="b1" Width="157" Margin="65,10" />
<Button Content="{Binding XPath=./BUTTONS/Button[2]/Text}" Click="b2_Click" Height="55" Name="b2" Width="157" Margin="65,10" />
<Button Content="{Binding XPath=./BUTTONS/Button[3]/Text}" Click="b3_Click" Height="55" Name="b3" Width="157" Margin="65,10" />
<Button Content="{Binding XPath=./BUTTONS/Button[4]/Text}" Click="b4_Click" Height="55" Name="b4" Width="157" Margin="65,10" />
<Button Content="{Binding XPath=./BUTTONS/Button[5]/Text}" Click="b5_Click" Height="55" Name="b5" Width="157" Margin="65,10" />
<Button Content="{Binding XPath=./BUTTONS/Button[6]/Text}" Click="b6_Click" Height="55" Name="b6" Width="157" Margin="65,10" />
<Button Content="{Binding XPath=./BUTTONS/Button[7]/Text}" Click="b7_Click" Height="55" Name="b7" Width="157" Margin="65,10" />
<Button Content="{Binding XPath=./BUTTONS/Button[8]/Text}" Click="b8_Click" Height="55" Name="b8" Width="157" Margin="65,10" />
<Button Content="{Binding XPath=./BUTTONS/Button[9]/Text}" Click="b9_Click" Height="55" Name="b9" Width="157" Margin="65,10" />
<Button Content="{Binding XPath=./BUTTONS/Button[10]/Text}" Click="b10_Click" Height="55" Name="b10" Width="157" Margin="65,10" />
</WrapPanel>
</ControlTemplate>
So, if i click on a Button, it fires its click event first, and then the click event of its parent; i mean the button that contains it (the one with the WrapPanel Template).
What i need is that when a button is pressed, to execute the click event of it, and just this, NOT the click event of its parent.
Thanks in advance!!
in the event handler:
private void b1_Click(object sender, RoutedEventArgs e)
{
e.Handled = true;
}
should work.
EDIT: I tried it. It works.

Categories