Passing argument to method in XAML with Caliburn Micro [WPF] - c#

I'd like to pass an argument in all my buttons to specify which button is clicked.
Right now I cant come further than:
<Button HorizontalAlignment="Left" Height="21" Margin="24,15,0,0" VerticalAlignment="Top" Width="66" Background="#FFE5E5E5" Grid.Column="2" Grid.Row="1" content="Details...
">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="ShowColumnDetailsView" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>

According to the documentation, you could do the following:
<Button Content="Click Me" x:Name="MyButton">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="SayHello">
<cal:Parameter Value="{Binding ElementName=MyButton}" />
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
Or did I miss something in the process?

Related

ItemSelectionChanged not invoking command action (Xceed.Wpf.Toolkit) - MVVM

I've been searching everywhere and can't get a solution to my issue (not sure if I'm over looking a simple matter). Anyhow, the issue I have is the command action is not being invoked on a CheckListBox (from Xceed.Wpf.Toolkit), please see following:
<wpftk:CheckListBox Grid.Column="0" Grid.Row="1" Grid.RowSpan="9" Width="250" Height="175" TabIndex="0" VerticalAlignment="Top"
ItemsSource="{Binding Path=GetAdminManagedDepartments}"
SelectedItemsOverride="{Binding SelectedDepartments, Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="ItemSelectionChanged">
<i:InvokeCommandAction Command="{Binding Path=SelectionCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</wpftk:CheckListBox>
However, the following for the combo box would work perfectly when invoking the same command:
<ComboBox Grid.Column="2" Grid.Row="1" Height="29" Width="230" FontSize="14" IsEditable="True" VerticalAlignment="Top" TabIndex="1"
ItemsSource="{Binding GetAllAbsenceTypes}"
Text="{Binding Path=TYPE_ABSENCE, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
SelectedItem="{Binding Path=TYPE_ABSENCE, Mode=TwoWay}"
ItemContainerStyle="{StaticResource ComboBoxItemStyle}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding Path=SelectionCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
Any help in this matter would be very much appreciated.

WPF XAML data binding with dynamically resizing UserControl

I have a UserControl with a grid containing text boxes. This object dynamically resizes itself with the text in the boxes. I need to bind the dimensions of this object to my model. Binding the 'Width' and 'Height' of the UserControl or Grid will break the dynamic resize, as the I am now stuck with whatever is the initial size declared in the model. I tried using 'minHeight' and 'minWidth' but these will not send data back to the model, as the minimum dimension never change. I have tried to fiddle with different modes(Oneway, ToWay etc..) but without luck.
So to sum up: I need a way to bind the dimensions while maintaining the dynamic resize with the text in the text boxes.
<UserControl x:Class="_02350Demo.View.ClassBoxUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Platform"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Canvas.Left="{Binding X}" Canvas.Top="{Binding Y}"
Width="{Binding Width}" Height="{Binding Height}">
<UserControl.InputBindings>
<KeyBinding Modifiers="Control" Key="Z" Command="{Binding UndoCommand}" />
<KeyBinding Modifiers="Control" Key="Y" Command="{Binding RedoCommand}" />
</UserControl.InputBindings>
<Grid>
<Rectangle Opacity="{Binding DataContext.ModeOpacity, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" StrokeThickness="6" StrokeDashArray="3.1">
<!-- The fill (background) color of the ellipse is a radial (center to edge) gradient (more than one color) brush. -->
<Rectangle.Fill>
<RadialGradientBrush>
<GradientStop Color="Black" Offset="0.0" />
</RadialGradientBrush>
</Rectangle.Fill>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<cmd:EventToCommand Command="{Binding DataContext.MouseDownShapeCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseMove">
<cmd:EventToCommand Command="{Binding DataContext.MouseMoveShapeCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseUp">
<cmd:EventToCommand Command="{Binding DataContext.MouseUpShapeCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition />
</Grid.RowDefinitions>
<TextBox Text="{Binding ContentClass}" HorizontalAlignment="Stretch" AcceptsReturn="True" TextWrapping="Wrap" VerticalAlignment="Stretch" Grid.Row="0" BorderThickness="1,1,1,1" BorderBrush="Gray" TextAlignment="Center" Margin="30,0,30,0"/>
<TextBox Text="{Binding ContentFields}" HorizontalAlignment="Stretch" AcceptsReturn="True" TextWrapping="Wrap" VerticalAlignment="Stretch" Grid.Row="1" BorderThickness="1,1,1,1" BorderBrush="Gray"/>
<TextBox Text="{Binding ContentMethods}" HorizontalAlignment="Stretch" AcceptsReturn="True" TextWrapping="Wrap" VerticalAlignment="Stretch" Grid.Row="2" BorderThickness="1,1,1,1" BorderBrush="Gray"/>
</Grid>
</Grid>
If you simply want your view model to know about the dynamic size of the UserControl, you could handle the SizeChanged event of the UserControl and set the Width and Height source properties of your view model to the ActualWidth and ActualHeight properties of the UserControl respectively:
private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
{
var vm = DataContext as YourViewModel;
vm.Height = ActualHeight;
vm.Width = ActualWidth;
}
You may wrap this in a behaviour if you want to: https://www.codeproject.com/Articles/28959/Introduction-to-Attached-Behaviors-in-WPF

Display Text in the Combobox

I have an wpf application.I want to show the selected item in the Combo box.
I get an error saying Cant use both DisplayMemberPath and Item Template.
My ItemsSource is not of string type
its a class called "StockExchange"
Following is my code :
<telerik:RadComboBox Grid.Column="1" DisplayMemberPath="StockExchangeName" Name="cmbStockExchange" Foreground="White" HorizontalAlignment="Left" HorizontalContentAlignment="Center" Margin="118,14,0,0" VerticalAlignment="Top" Width="100" Height="23" ItemsSource="{Binding StockExchange, Mode=TwoWay}" SelectedItem="{Binding SelectedStockExchange,Mode= TwoWay}" telerik:StyleManager.Theme="Summer" TabIndex="3">
<telerik:RadComboBox.ItemTemplate >
<DataTemplate>
<CheckBox Name="StockExchange" Content="{Binding StockExchangeName}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<Commands:EventToCommand Command="{Binding DataContext.StockExchangeCheckedCmd,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type telerik:RadWindow}}}" CommandParameter="{Binding ElementName=StockExchange}" ></Commands:EventToCommand>
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<Commands:EventToCommand Command="{Binding DataContext.StockExchangeUnCheckedCmd,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type telerik:RadWindow}}}" CommandParameter="{Binding ElementName=StockExchange}" ></Commands:EventToCommand>
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
</DataTemplate>
</telerik:RadComboBox.ItemTemplate>
</telerik:RadComboBox>
what is solution for this? how can I display single or multiple selected Items in a Combo box?
<telerik:RadComboBox Grid.Column="1" Name="cmbStockExchange" Foreground="White" HorizontalAlignment="Left" HorizontalContentAlignment="Center" Margin="118,14,0,0" VerticalAlignment="Top" Width="100" Height="23" ItemsSource="{Binding StockExchange, Mode=TwoWay}" SelectedItem="{Binding SelectedStockExchange,Mode= TwoWay}" telerik:StyleManager.Theme="Summer" TabIndex="3">
<telerik:RadComboBox.ItemTemplate >
<DataTemplate>
<CheckBox Name="StockExchange" Content="{Binding StockExchangeName}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<Commands:EventToCommand Command="{Binding DataContext.StockExchangeCheckedCmd,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type telerik:RadWindow}}}" CommandParameter="{Binding ElementName=StockExchange}" ></Commands:EventToCommand>
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<Commands:EventToCommand Command="{Binding DataContext.StockExchangeUnCheckedCmd,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type telerik:RadWindow}}}" CommandParameter="{Binding ElementName=StockExchange}" ></Commands:EventToCommand>
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
</DataTemplate>
</telerik:RadComboBox.ItemTemplate>
Create a Textblock that Shows the selected item StockExchangeName
<TextBlock Text="{Binding Path=SelectedItem.StockExchangeName, ElementName=cmbStockExchange}" />
If you select CheckBox, no item is shown selected in comboBox because no item is selected since click event is handled by checkbox.
You can bind IsChecked with IsSelected value of ComboBoxItem so that on click of checkbox corresponding item gets selected.
<CheckBox Content="{Binding StockExchangeName}"
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource
Mode=FindAncestor, AncestorType=ComboBoxItem}}"/>
This will show checkBox in comboBox because you have provided template with checkBox in it for comboBoxItem.

Different Commands For Different Events in a ListBox

I have the following ListBox :
<ListBox ItemsSource="{Binding CityList}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:name="Name" Text="{Binding Name }" />
<TextBlock x:name="Country" Text="{Binding Country}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The following article explains very well how to implement SelectionChanged :
<phone:LongListSelector x:Name="Results" Margin="0,0,-12,0" ItemsSource="{Binding Events}" SelectedItem="{Binding Event}">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17">
<TextBlock Text="{Binding benchmark.name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding summary}" TextWrapping="Wrap" Style="{StaticResource PhoneTextNormalStyle}"/>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<command:EventToCommand Command="{Binding WodSelectedCommand, Mode=OneWay}" CommandParameter="{Binding Path=SelectedItem, ElementName=Results}" PassEventArgsToCommand="False"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</phone:LongListSelector>
But in this example the Selection Changed will be the same for every Textblocks in my example i would like that my two textblocks have two different commands.
How can i do so ?
Put the event triggers inside the DataTemplate. That should let you have two different commands for tap on Name and Country.
<ListBox ItemsSource="{Binding CityList}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:name="Name" Text="{Binding Name }" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<command:EventToCommand Command="{Binding NameSelectedCommand, Mode=OneWay}" CommandParameter="{Binding Path=SelectedItem, ElementName=CityList}" PassEventArgsToCommand="False"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
<TextBlock x:name="Country" Text="{Binding Country}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<command:EventToCommand Command="{Binding CountrySelectedCommand, Mode=OneWay}" CommandParameter="{Binding Path=SelectedItem, ElementName=CityList}" PassEventArgsToCommand="False"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Is there anyway of consolidating similar data bindings and/or triggers in XAML?

I have a user control that hosts other controls. The way I implemented this is via data templates that define the control that should be associated with a specific view-model. These view-models have similar properties and interaction triggers. Please see XAML snippet below.
The problem with this approach is that I would have to copy-paste the data bindings if I want to support a new view-model. Is there any way of consolidating all similar data bindings and/or triggers into one template? I don't want to type/copy-paste the same data binding definitions into each control. (Yes, I know, I'm that lazy.)
<UserControl.Resources>
<DataTemplate DataType="{x:Type vm:SomeViewModel1}">
<TextBlock Canvas.Left="{Binding Left}"
Canvas.Top="{Binding Top}"
RenderTransform="{Binding Transform}"
Height="{Binding Height}"
Width="{Binding Width}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<cmd:EventToCommand Command="{Binding MouseEnterCommand}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeave">
<cmd:EventToCommand Command="{Binding MouseLeaveCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SomeViewModel2}">
<Rectangle Canvas.Left="{Binding Left}"
Canvas.Top="{Binding Top}"
RenderTransform="{Binding Transform}"
Height="{Binding Height}"
Width="{Binding Width}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<cmd:EventToCommand Command="{Binding MouseEnterCommand}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeave">
<cmd:EventToCommand Command="{Binding MouseLeaveCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SomeViewModel3}">
<Button Canvas.Left="{Binding Left}"
Canvas.Top="{Binding Top}"
RenderTransform="{Binding Transform}"
Height="{Binding Height}"
Width="{Binding Width}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<cmd:EventToCommand Command="{Binding MouseEnterCommand}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeave">
<cmd:EventToCommand Command="{Binding MouseLeaveCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SomeViewModel4}">
<!-- Do not want copy-paste code here... -->
</DataTemplate>
</UserControl.Resources>
You can use common style, and put both your properties and triggers (which are also properties) inside this style, look at this StackOverflow question
for more details.
What about putting the triggers into a resource and associating them with your controls. Or use a custom base class for your DataTemplates.

Categories