Button Command inside a popupbox, binding not working - c#

I have a button (x:name="MyButton") inside a PopuBox in wpf.
<materialDesign:PopupBox PlacementMode="BottomAndAlignRightEdges"
StaysOpen="True"
Padding="0 0 -1 0"
VerticalAlignment="Center">
<materialDesign:PopupBox.ToggleContent>
<materialDesign:PackIcon Kind="Calendar"
Foreground="{StaticResource PrimaryHueLightBrush}"
Width="20"
Height="20"
VerticalAlignment="Center"/>
</materialDesign:PopupBox.ToggleContent>
<Button Content="Ok"
x:Name ="MyButton"
Style="{DynamicResource MaterialDesignFlatButton}"
Margin="0 5 40 5"
Command="{Binding ClosePopUp}"/>
</materialDesign:PopupBox>
The problem is that when i click the button (MyButton), the command won't work. I think that has to do with the binding. Every button outside the popubox works correctly.
Any idea what's wrong?
EDIT
The PopupBox is inside a DataTemplate

I resolved by replacing Command="{Binding ClosePopUp} with Command="{Binding DataContext.ClosePopUp, RelativeSource={RelativeSource AncestorType=UserControl}}"
The datacontext of the button should be equal to its parent.

Related

WPF MaterialDesign Dialog Host

I am building a WPF application and I would like to have custom MessageBox but I saw that is really tedious and I thought of using the DialogHost provided by MaterialDesign. The problem is that I can't get it to work the way I want it to so let me describe the current behaviour and the wanted one.
The current behaviour:
<materialDesign:ColorZone Grid.Column="1"
Grid.ColumnSpan="2"
Grid.Row="1"
Mode="Light"
Padding="16">
<DockPanel>
<materialDesign:DialogHost DockPanel.Dock="Right">
<Button x:Name="PowerButton"
ToolTip="{Binding PowerButtonToolTip, Source={StaticResource ResourceKey=ButtonsResources}}"
Style="{StaticResource MaterialDesignIconButton}"
Command="{x:Static materialDesign:DialogHost.OpenDialogCommand}">
<Button.CommandParameter>
<StackPanel>
<TextBlock Text="TODO" />
<StackPanel Orientation="Horizontal"
Margin="0, 20, 0, 10">
<Button Width="90"
Height="30"
Margin="10, 0, 0, 0"
Style="{StaticResource MaterialDesignOutlinedButton}"
Click="PowerButton_Click">
OK
</Button>
<Button Width="90"
Height="30"
Margin="10, 0, 10, 0"
Style="{StaticResource MaterialDesignOutlinedButton}"
Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}">
CANCEL
</Button>
</StackPanel>
</StackPanel>
</Button.CommandParameter>
<materialDesign:PackIcon Kind="Power" />
</Button>
</materialDesign:DialogHost>
<StackPanel Orientation="Horizontal">
<ToggleButton x:Name="MenuButton"
Style="{DynamicResource MaterialDesignHamburgerToggleButton}" />
<TextBlock VerticalAlignment="Center"
Margin="16 0 0 0"
Text="{Binding MainViewTitle, Source={StaticResource ResourceKey=ViewsResources}}">
</TextBlock>
</StackPanel>
</DockPanel>
</materialDesign:ColorZone>
What happens is that when I'm clicking the PowerButton the DialogHost appears with the structure from the Button.CommandParameter. The issue with this is that the window doesn't get "disabled" (getting a little black and unclickable) while the dialogue is on.
I saw that to achieve this behaviour I need to but all the content of the window inside the DialogHost. But is it really so or I am misunderstanding something? Their example (see link) isn't really helpful because there seem to be other things running in the background. Moreover, the command materialDesign:DialogHost.OpenDialogCommand of the button that is opening the "Topmost dialogue host" seems limited to me.
Let's try something simple fo you to try at the first time.
The DialogHost is composed of two major parts
First everything that is displayed into your DialogHost, this have to be into one block (StackPanel, Grid, DockPanel...) that is the content of your DialogHost.
Second part is more like the context of your dialog, when you want to display it have to be somewhere to be displayed, another block (StackPanel, Grid, DockPanel...), the context is the place where your dialog will be once displayed, il will show centered and darken the rest of the block.
Now you have the main theory let's make a simple sample based on the sample given by the demo and your piece of code.
<materialDesign:DialogHost HorizontalAlignment="Center" VerticalAlignment="Center">
<materialDesign:DialogHost.DialogContent>
<StackPanel Margin="16">
<!-- HERE GOES YOUR CONTENT -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
<Button Style="{StaticResource MaterialDesignFlatButton}" IsDefault="True"
Margin="0 8 8 0" Command="materialDesign:DialogHost.CloseDialogCommand">
<Button.CommandParameter>
<system:Boolean>True</system:Boolean>
</Button.CommandParameter>
ACCEPT
</Button>
<Button Style="{StaticResource MaterialDesignFlatButton}"
IsCancel="True" Margin="0 8 8 0"
Command="materialDesign:DialogHost.CloseDialogCommand">
<Button.CommandParameter>
<system:Boolean>False</system:Boolean>
</Button.CommandParameter>
CANCEL
</Button>
</StackPanel>
</StackPanel>
</materialDesign:DialogHost.DialogContent>
<!-- START OF YOUR CONTEXT-->
<!-- END OF YOUR CONTEXT -->
</materialDesign:DialogHost>
So now you have the basis that may be enough for you to start enjoying.
A little more, your context need to be large enough to display what you put on your DialogHost so you can't put a whole dialog around a button, it is better to make it around something bigger, as a first try you should try on a new page to test this context :
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Button x:Name="PowerButton" ToolTip="{Binding PowerButtonToolTip, Source={StaticResource ResourceKey=ButtonsResources}}"
Style="{StaticResource MaterialDesignIconButton}"
Command="{x:Static materialDesign:DialogHost.OpenDialogCommand}">
</Grid>
The Buttons under the content are simply there if you desire to do an action, for example if the DialogHost is there for a modification or a choice where the user can say Yes or No then rename ACCEPT and CANCEL as you want. The "IsDefault" is there to make that it is this button that is considered as pressed if the user press Enter. Pressing a button automatically close the Dialog that is good to know.
And as the both ACCEPT and CANCEL are button you can affect a Click event that will be pretty useful for advanced using of the DialogHost.

How to use click event in MaterialDesign:PackIcon in WPF?

I used materialDesign:PackIkon in my WPF application.
this is my code at xaml for the PackIcon
<ListViewItem Background="White" Height="55" >
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="CardMembership" MouseDown="PackIconMember_MouseDown" Height="40" Width="25" Foreground="#FF0959A8" />
<Button x:Name="btnMember" Click="btnMember_Click" Content="Member" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="Black" FontSize="10" />
</StackPanel>
</ListViewItem>
I have a few PackIcon in my xaml. each of them in different listview.
what I want is when user click on the Icon it will process the event in PackIconMember_MouseDown
There is no error in my code above, the problem is sometimes the code work. I means when user click on the icon it will process the event. but sometimes user need to click multiple time for it to process the event. I don't know why this happen.
Any idea on what I should do with this ? or any suggestion to replace the MouseDown event.
its only work when I click on icon with the blue color.
it does not working when I click on the white space that I show with the arrow. how can I do to make it work when user click anywhere on the icon ? is it possible ?
if I do inside button, the packIcon does not appear
<Button Background="{x:Null}" BorderBrush="{x:Null}" Foreground="Black" Height="20" Width="25" Margin="10">
<materialDesign:PackIcon MouseDown="PackIconMember_MouseDown" TouchDown="PackIconMember_MouseDown" Kind="CardMembership" />
</Button>
Set the Background property of the PackIcon to Transparent:
<materialDesign:PackIcon Kind="CardMembership" MouseDown="PackIconMember_MouseDown" Height="40" Width="25" Foreground="#FF0959A8"
Background="Transparent" />
This should capture the clicks also on the "empty" parts of the icon.
Make The Icon as Part of the Button Like:
<Button x:Name="btnMember" Click="btnMember_Click" Content="Member" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="Black" FontSize="10" >
<materialDesign:PackIcon Kind="CardMembership" Height="40" Width="25" Foreground="#FF0959A8" />
</Button
But you have to set the margin

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.

Material Design WPF Command Issue

I am using Material Design for WPF. I am trying to use Dialogs.
Here is my dialog content:
<materialDesign:DialogHost.DialogContent>
<Label></Label>
</materialDesign:DialogHost.DialogContent>
I have also popup box with buttons what generate dialogs. Popup dialog is inside of DialogHost as below:
<materialDesign:DialogHost HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="0" Grid.Column="8">
<materialDesign:PopupBox Style="{StaticResource MaterialDesignMultiFloatingActionAccentPopupBox}" PlacementMode="BottomAndAlignCentres">
<materialDesign:PopupBox.ToggleCheckedContent>
<materialDesign:PackIcon Kind="Close" Width="24">
</materialDesign:PopupBox.ToggleCheckedContent>
<StackPanel>
<Button ToolTip="Add Audio" Background="#449AB8" BorderBrush="#449AB8" Command="{Binding AddAudioCommand}">
<materialDesign:PackIcon Foreground="White" Kind="Microphone" />
</Button> <!-- This Command is working-->
<Button ToolTip="Add Picture" Background="#449AB8" BorderBrush="#449AB8" Command="{x:Static materialDesign:DialogHost.OpenDialogCommand}">
<materialDesign:PackIcon Foreground="White" Kind="Camera" />
<Button.CommandParameter>
<StackPanel Margin="16">
<TextBlock HorizontalAlignment="Center" FontSize="15">
Add Image
</TextBlock>
<Button Style="{StaticResource MaterialDesignFlatButton}" IsDefault="True" Margin="0 10 10 0" Command="{Binding Path=AddPictureCommand}">
Attach from disc
</Button>
<Button Style="{StaticResource MaterialDesignFlatButton}" IsCancel="True" Margin="0 8 8 0">
Take a photo
</Button>
<Button Style="{StaticResource MaterialDesignFlatButton}" IsCancel="True" Margin="0 8 8 0" Command="materialDesign:DialogHost.CloseDialogCommand">
<Button.CommandParameter>
<system:Boolean>False</system:Boolean>
</Button.CommandParameter>
Discard
</Button>
</StackPanel>
</Button.CommandParameter>
</Button>
</stackpanel>
...
As I understand I am sending layout of Dialog to DialogContent. However first button's command is working (Add Audio).
Second button 'Add Picture' sends StackPanel to DialogContent. Dialog is working, it does appear but my Command doesn't work. It's weird because Command to close is working.
The problem is it doesn't get into Command Execute method.
I think that it isn't weird that CloseDialogCommand is executing - it indicates to your Dialog.
And you are trying to execute AddPictureCommand at context of this Dialog.
Try to find out how to pass your parent as a DataContext or maybe (probably better idea) use dedicated MVVM solution to bind content od dialog (your StackPanel) with some code.
There are few solutions of dealing with dialogs on wiki of MaterialDesign project

Conditional CommandParameter binding with ElementName, Path is child of child

I have following hierarchy -
<TabControl x:Name="tabControl1" FontWeight="Black" BorderThickness="1" BorderBrush="Black" Background="LightBlue" >
<local:ClosableTab Background="LightBlue" Title="New Tab" x:Name="PreviewWindow">
<Grid>
<Border Name="mask" Background="Black" CornerRadius="5"/>
<Grid>
<Grid.OpacityMask>
<VisualBrush Visual="{Binding ElementName=mask}"/>
</Grid.OpacityMask>
<WebBrowser Name="webBrowser" Source="http://www.google.com" Margin="0" Navigated="webBrowser_Navigated" />
</Grid>
</Grid>
</local:ClosableTab>
</TabControl>
Questions
How can I bind WebBrowser with CommandParameter, by selected TabIndex of tabControl1
I am trying following code -
<Button Name="btnRefresh" Content="Refresh" Command="{Binding Path=Refresh}" CommandParameter="{Binding ElementName=tabControl1,Path=SelectedIndex}"></Button>
How can I do this conditionally. e.g. If SelectedIndex>3 then Command should fire.
Update
My goal is to refresh web browser via ViewModel Command. The .xaml file has differen tabs with its own WebBrowsers, so by SelectedIndex, I can figure out that WebBrowser, which I want to pass in CommandParameter.

Categories