I have the following XAML snippet:
<TextBox x:Name="FilterTB" TextChanged="FilterTB_TextChanged"/>
<Button x:Name="CancelFilterSelectionButton" FontWeight="Bold" Content="X"/>
I'd like to erase the content of the TextBox when the user presses the Button.
Of course doing so from Code Behind is a trivial task, but I wanted to accomplish it only through the use of XAML, and so using Triggers.
I tried researching on the net, but I either found uncorrect solutions, or overly-convoluted solutions, so I'd like to hear some clean and compact solutions.
Here I had a spare minute, hope this helps, cheers.
namespaces;
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
and easy peasy.
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBox x:Name="ThatThangToClear" Width="250"/>
<Button x:Name="ClearThatThang" Content="Clear That Thang" Margin="5,0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:ChangePropertyAction
TargetName="ThatThangToClear"
TargetObject="{Binding ElementName=ThatThangToClear}"
PropertyName="Text" Value="{x:Null}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</StackPanel>
Oh, and P.S. - You really only need either TargetName OR TargetObject but I included both for examples sake.
Related
I'm developing a WPF application and using Caliburn.Micro for MVVM. I'need to dynamically add buttons into view during the runtime.
I have done some research and I got to know that I can achieve this using an ItemControl.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<ItemsControl>
<Button x:Name="ExecuteMethod1" Content="Execute1" />
<Button x:Name="ExecuteMethod2" Content="Execute2" />
<Button x:Name="ExecuteMethod3" Content="Execute3" />
</ItemsControl>
</Grid>
</Window>
Caliburn.Micro's convention allows to call a method which matches to Button's x:Name property. In above code button named ExecuteMethod1 will call a method ExecuteMethod1() in ViewModel.
Problem:
As I'm adding buttons dynamically how can I set the X:Name property for buttons?
I tried to set it using Binding, but WPF doesn't allow to bind X:Name property.
Is there any alternatives? Could anyone can help me with a suggestion?
I am not sure if this a new feature. Got it working from the Caliburn Micro Documentation.
Add Windows Interactivity Assembly. You can pass to your action the Name or the Content of the Button that shall be enough to identify which button was clicked and perform the right action.
CaliburnMicro Actions
<UserControl x:Class="Caliburn.Micro.HelloParameters.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cal="http://www.caliburnproject.org">
<StackPanel>
<TextBox x:Name="Name" />
<Button Content="Click Me">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="SayHello">
<cal:Parameter Value="{Binding ElementName=Name, Path=Text}" />
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</StackPanel>
</UserControl>
I have a grid with a viewbox and a path in it. I want on grid mouse over to change the fill of the path. But the mouse over fires only when directly over a path, it ignores the grid.
I looked all over the web, but i couldn't find anywhere where this problem is mentioned.
xaml:
<Grid Grid.Column="0" Margin="15" x:Name="gdOpenBrowser">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<i:InvokeCommandAction Command="{Binding OpenBrowserCursorCommand}"
CommandParameter="{Binding ElementName=gdOpenBrowser}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:InvokeCommandAction Command="{Binding LoginButtonCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Viewbox>
<Viewbox.RenderTransform>
<TranslateTransform X="-10" Y="-5"/>
</Viewbox.RenderTransform>
<Path Fill="White" Data="M38 8H10c-2.21 0-4 1.79-4 4v24c0 2.21 1.79 4 4 4h8v-4h-8V16h28v20h-8v4h8c2.21 0 4-1.79 4-4V12c0-2.21-1.79-4-4-4zM24 20l-8 8h6v12h4V28h6l-8-8z"/>
</Viewbox>
</Grid>
As mentioned in the comment if you want whole Grid to be hit test visible you need to initialize Background property of the Grid with some brush, for example Transparent which will have same visual effect as null but will make whole Grid hit test visible.
<Grid ... x:Name="gdOpenBrowser" Background="Transparent">
I've tried to solve the following problem for several hours now:
I'm developing a game, where I have to switch between several views. When I'm in the game view, at the end there is a button called "Return match" which navigates back to the "PlayerSelectView" where the players are set up:
<Button Tag="{Binding Source={StaticResource Options}, Path=Effect}" Width="300" MinHeight="70">
<localControls:DropShadowTextBlock Text="{Binding LocalizedText.GV_ReturnMatch}"/>
<i:Interaction.Triggers>
<ic:DataTrigger Binding="{Binding Result, ElementName=MessageBoxBehavior}" Value="OK">
<i:InvokeCommandAction Command="{Binding NewGameCommand}" />
<ic:NavigateToPageAction TargetPage="/Views/PlayerSelectView.xaml" />
</ic:DataTrigger>
</i:Interaction.Triggers>
<i:Interaction.Behaviors>
<behaviors:MessageBoxBehavior x:Name="MessageBoxBehavior" Text="{Binding LocalizedText.MAIN_YouWillLoseYourPreviousGame}" IsEnabled="{Binding IsGameInitialized}" />
</i:Interaction.Behaviors>
</Button>
The NewGameCommand doesn't reset the players list in the PlayerSelectViewModel.
At this time the constructor of PlayerSelectView and the constructor in the PlayerSelectViewModel is not called, so it preserves the state, as it should be, but, going back to the menu during the game with this code:
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
GameViewModel.Instance.GameIsPaused = true;
NavigationService.Navigate(new Uri("/Views/MainPageView.xaml", UriKind.Relative));
}
and after that going back to the GameView with the Continue button:
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="{Binding IsGameInitialized, Converter={StaticResource BoolToVisibilityConverter}}" Tag="{Binding Source={StaticResource Options}, Path=Effect}" Width="300" MinHeight="70" FontWeight="Normal">
<localControls:DropShadowTextBlock Text="{Binding LocalizedText.MAIN_Continue}"/>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<ic:NavigateToPageAction TargetPage="/Views/GameView.xaml" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
When I now hit "Return Match", the PlayerSelectView always gets reinitialized!
Why does it now reinitialize the PlayerSelectView? The other thing is, that when the new players are set up again and the game is started, it just returns to the Game Over screen (which is a popup layer on the GameView).
Does anyone have an idea what to do?
UPDATE:
When the game starts, the MainView is shown. From there the user is taken to the PlayerSelectView with this button:
<Button Tag="{Binding Source={StaticResource Options}, Path=Effect}" Width="300" MinHeight="70">
<localControls:DropShadowTextBlock Text="{Binding LocalizedText.MAIN_NewGame}"/>
<i:Interaction.Triggers>
<ic:DataTrigger Binding="{Binding Result, ElementName=MessageBoxBehavior}" Value="OK">
<i:InvokeCommandAction Command="{Binding NewGameCommand}" />
<ic:NavigateToPageAction TargetPage="/Views/PlayerSelectView.xaml" />
</ic:DataTrigger>
</i:Interaction.Triggers>
<i:Interaction.Behaviors>
<behaviors:MessageBoxBehavior x:Name="MessageBoxBehavior" Text="{Binding LocalizedText.MAIN_YouWillLoseYourPreviousGame}" IsEnabled="{Binding IsGameInitialized}" />
</i:Interaction.Behaviors>
</Button>
Here players are created and edited. The game starts with this button:
<Button Command="{Binding StartGameCommand}" CommandParameter="{Binding NavigationService, ElementName=PlayerSelectViewControl}" Tag="{Binding Source={StaticResource Options}, Path=Effect}" Padding="0">
<localControls:DropShadowTextBlock Text="{Binding LocalizedText.PLSEL_StartGame}"/>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<ic:NavigateToPageAction TargetPage="/Views/GameView.xaml"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
...which runs this code as well:
private void StartGame()
{
BusinessLogic.GameLogic.Initialize(new List<Player>(Players));
}
From there, the user can go back to the MainView (menu), exit the game (the state is preserved) or change options.
<DataTemplate DataType="{x:Type local:TestModel}">
<Button Content="Button" " Margin="0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<mvvm:EventToCommand
Command="{Binding ImageClick, Mode=OneWay}"
MustToggleIsEnabledValue="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</DataTemplate>
Hi all,
Above I have a data template which is switching on certain data type using a data template. I am using the mvvm pattern. I want to be to bind to the ImageClick property.
I was able to do this before, but since I have moved the button inside the data template I am unable to bind to that property.
I think I need to use Relative source for the binding but am really unsure how to do it.
Help on this would be amazing.
Thanks.
You may try the below.
<Button Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type YourViewModel}}, Path=DataContext.ImageClick}" />
I think it would help you..
I am trying to use AttachedCommandBehavior V2 to translate ListBoxItem events such as double click into commands that are execute against the view model.
I want to fire commands for multiple events, this is the example code I am trying to emulate:
<Border Background="Yellow" Width="350" Margin="0,0,10,0" Height="35" CornerRadius="2" x:Name="test">
<local:CommandBehaviorCollection.Behaviors>
<local:BehaviorBinding Event="MouseLeftButtonDown" Action="{Binding DoSomething}" CommandParameter="An Action on MouseLeftButtonDown"/>
<local:BehaviorBinding Event="MouseRightButtonDown" Command="{Binding SomeCommand}" CommandParameter="A Command on MouseRightButtonDown"/>
</local:CommandBehaviorCollection.Behaviors>
<TextBlock Text="MouseDown on this border to execute the command"/>
</Border>
Since I want to apply that to a ListBoxItem, I am trying to do it through a style by doing:
<ListBox.ItemContainerStyle>
<Style>
<Setter Property="acb:CommandBehaviorCollection.Behaviors">
<Setter.Value>
<acb:CommandBehaviorCollection>
<acb:BehaviorBinding Event="MouseDoubleClick" Command="{Binding DataContext, RelativeSource={RelativeSource AncestorType=ListBox}}" CommandParameter="{Binding}"/>
<acb:BehaviorBinding Event="KeyUp" Command="{Binding DataContext, RelativeSource={RelativeSource AncestorType=ListBox}}" CommandParameter="{Binding}"/>
</acb:CommandBehaviorCollection>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
But I get a compile error with that code that says error MC3089: The object 'CommandBehaviorCollection' already has a child and cannot add 'BehaviorBinding'. 'CommandBehaviorCollection' can accept only one child. Line 39 Position 11.
Also if I comment out one of the BehaviorBindings then it compiles but I get a runtime xaml load exception saying "Value cannot be null. Parameter name: property", so I'm not sure if I'm even taking the correct approach.
Can anyone provide an example of the correct syntax to set multiple behavior bindings on a ListBoxItem?
My solution uses interaction triggers and the ItemTemplate not the ItemContainerStyle.
This invokes a mouse double click or key up command in the text box, not the whole list box item.
<UserControl.Resources>
<DataTemplate DataType="{x:Type ViewModel:DataItem}" x:Key="ItemTemplate">
<ContentControl>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding DoubleClickCommand}"/>
</i:EventTrigger>
<i:EventTrigger EventName="KeyUp">
<i:InvokeCommandAction Command="{Binding KeyUpCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<TextBox Text="{Binding Name}">
</TextBox>
</ContentControl>
</DataTemplate>
</UserControl.Resources>
<ListBox x:Name="listBox" ItemTemplate="{StaticResource ItemTemplate}" ItemsSource={Binding Items} />
Where DataItem is something like
class DataItem : INotifyPropertyChanged
{
public string Name{get;set}
.. etc
}
and the view model set on the DataContext has an IList<DataItems> Items{get; private set} property.