I want to invoke a Command from view model inside radio button ControlTemplate. And do it when event Checked is raised
I tried this:
<ControlTemplate x:Key="RequestTypeControlTemplate" TargetType="RadioButton">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0,0,0,2">
<ContentPresenter Margin="10,0,10,0">
<i:Interaction.Triggers>
<!-- Checked event from parent -->
<i:EventTrigger EventName="Checked">
<!-- Command from view model and binding to tag of radio button as arg -->
<i:InvokeCommandAction Command="{Binding DataContext.OnTypeChangedCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" CommandParameter="{Binding Tag, RelativeSource={RelativeSource TemplatedParent}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ContentPresenter>
</Border>
</ControlTemplate>
But I think event goes from ContentPresenter, not from RadioButton. How do I get the event from RadioButton?
EDIT:
<RadioButton Content="All requests"
ContentTemplate="{StaticResource RadioButtonDataTemplate}"
GroupName="Filter"
IsChecked="True"
Style="{StaticResource RadioButtonStyle}"
Template="{StaticResource RequestTypeControlTemplate}"
Tag="{x:Static local:ContentType.Any}"/>
In viewModel
public ICommand OnTypeChangedCommand
{
get
{
return m_TypeChangedCommand ?? (m_TypeChangedCommand = new DelegateCommand<ContentType>(OnTypeChanged));
}
}
public void OnTypeChanged(ContentType type)
{
Debug.WriteLine(type);
}
You can't do that because the Routed event is only handled from the element (bubble) or to the element (tunnel)
What you can use is a DataTrigger on IsChecked property .
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
<i:Interaction.Triggers>
<ei:DataTrigger Binding="{Binding IsChecked,RelativeSource={RelativeSource AncestorType=RadioButton}}" Value=True>
<i:InvokeCommandAction Command="{Binding DataContext.OnTypeChangedCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" CommandParameter="{Binding Tag, RelativeSource={RelativeSource AncestorType=RadioButton}}}" />
</ei:DataTrigger>
</i:Interaction.Triggers>
Related
I put the button inside the gridsplitter. my intention is to make clickable gridsplitter as well as slideable. my problem is after putting button inside the grid splitter, totally cannot drag by mouse. how can i configure the grid splitter to clickable and slideable.
<GridSplitter BorderThickness="1" HorizontalAlignment="Stretch" Grid.Column="1" >
<GridSplitter.Template>
<ControlTemplate TargetType="{x:Type GridSplitter}">
<Grid>
<Button Name="btnSplit" Content="⁞" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding SplitterClickCommand}" CommandParameter="{Binding ElementName=btnSplit}" ></i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
</ControlTemplate>
</GridSplitter.Template>
</GridSplitter>
Best Rgds
df
Try to subscribe MouseDoubleClick event on GridSplitter:
<GridSplitter BorderThickness="1" HorizontalAlignment="Stretch" Grid.Column="1" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding SplitterClickCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</GridSplitter>
If MouseDoubleClick event is not suitable for you, you can try to subscribe to MouseDown or MouseLeftButtonDown.
I have a problem. I am trying to create a context menu with databinding in wpf. The context menu items would are bound to an observable collection of objects. The population of context menu is fine - however, I want to add the command to it.
The way I am using it is:
in XAML
<Grid.Resources>
<local:RestoreCommand x:Key="RestoreCommand" />
<local:ShowBalloonCommand x:Key="BaloonCommand" />
<local:StartTaskCommand x:Key="StartTaskCommand" />
</Grid.Resources>
<ContextMenu ItemsSource="{Binding}" Name="taskBarContextMenu">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{StaticResource StartTaskCommand}"/>
<Setter Property="CommandParameter" Value="{Binding mainWindow}"/>
</Style>
</ContextMenu.ItemContainerStyle>
and
<TextBlock TextWrapping="Wrap" Text="{Binding Name}" Grid.Column="0"/>
<TextBlock TextWrapping="Wrap" Text="{Binding TimeElapsed, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Column="2"/>
and in C#:
taskbarIcon.ContextMenu.ItemsSource = TasksList;
And I have a class for the command
public class StartTaskCommand : ICommand
{
public void Execute(object parameter)
{
//THE PARAMETER IS ALWAYS NULL
var window = parameter as MainWindow;
if (window != null)
{
}
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
}
I have it set up simiarly for other two commands and it works fine. Anything I try to add as the parameter is always null - be it taskBarContextMenu, or mainWindow or menuItem...
Any ideas welcome.
====
I tried a following solution as suggested, but the command parameter is still null:
<tb:TaskbarIcon Name="taskbarIcon"
DoubleClickCommand="{StaticResource RestoreCommand}"
DoubleClickCommandParameter="{Binding ElementName=mainWindow}"
LeftClickCommand="{StaticResource BaloonCommand}"
LeftClickCommandParameter="{Binding ElementName=mainWindow}"
IconSource=".\256px-Out_of_date_clock_icon.ico"
MenuActivation="RightClick"
Tag="{Binding ElementName=mainWindow}"
>
<tb:TaskbarIcon.ContextMenu ><ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}" Tag="{Binding}" Name="taskBarContextMenu">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{StaticResource StartTaskCommand}"/>
<Setter Property="CommandParameter" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.DataContext}"/>
</Style>
</ContextMenu.ItemContainerStyle>
You need to add a tag to the menu's container and bind to it using placement target.
View this example:
<StackPanel x:Key="ConfigurationListItem" x:Shared="False" Tag="{Binding ElementName=UserControl}">
<StackPanel Orientation="Horizontal">
<Button>
<Button.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding ElementName=UserControl, Path=LaunchCommand}" CommandParameter="{Binding}" />
<MouseBinding Gesture="LeftClick" Command="{Binding ElementName=UserControl, Path=SelectCommand}" CommandParameter="{Binding}" />
</Button.InputBindings>
</StackPanel>
<StackPanel.ContextMenu>
<ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}" Tag="{Binding}">
<MenuItem Header="Sync Environment Dependencies"
Command="{Binding Parent.PlacementTarget.Tag.SyncEnvironmentCommand, RelativeSource={RelativeSource Self}}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.DataContext}" />
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
I am trying to use the Mvvm Light toolkit to bind an event to a command from within a style.
I currently have the style:
<Style
xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:controls='clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:d='http://schemas.microsoft.com/expression/blend/2008'
xmlns:mc='http://schemas.openxmlformats.org/markup-compatibility/2006'
xmlns:ig='http://schemas.infragistics.com/xaml'
xmlns:i='http://schemas.microsoft.com/expression/2010/interactivity'
xmlns:Command='clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4'
TargetType='ig:EventSpan'>
<Setter Property='Template'>
<Setter.Value>
<ControlTemplate TargetType='ig:EventSpan'>
<Grid Margin='0,2,0,2'>
<i:Interaction.Triggers>
<i:EventTrigger EventName='MouseEnter'>
<Command:EventToCommand Command='{Binding EventSpan_MouseEnter1}' CommandParameter='{Binding RelativeSource={RelativeSource AncestorType={x:Type ig:EventSpan}}}'/>
</i:EventTrigger>
<i:EventTrigger EventName='MouseLeave'>
<Command:EventToCommand Command='{Binding EventSpan_MouseLeave1}' CommandParameter='{Binding RelativeSource={RelativeSource AncestorType={x:Type ig:EventSpan}}}'/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Rectangle RadiusX='0' RadiusY='0' Fill='{TemplateBinding Fill}' Stroke='{TemplateBinding Stroke}' StrokeThickness='0' Height='0' Margin='0, 0, 0, 0' VerticalAlignment='Top' />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and an example of the code behind is:
private RelayCommand<string> _eventSpan_MouseEnter;
public RelayCommand<string> EventSpan_MouseEnter1
{
get
{
return _eventSpan_MouseEnter
?? (_eventSpan_MouseEnter = new RelayCommand<string>(
sender =>
{
MouseOverLayer = sender;
}));
}
}
But this command never fires and I cannot work out why?
PS. The reason that the libraries are referenced in the styles is because this style is loaded dynamically from code behind. It is legacy code that I am currently trying to convert to mvvm.
So There were two problems with the way I had bound before. Firstly the main reason was that the style had no datacontext. And apparently didnt inherit the datacontext from the template implementing the style. and also that the command parameter was incorrect.
CommandParameter='{Binding RelativeSource={RelativeSource AncestorType={x:Type ig:EventSpan}}}'
was binding to a relaycommand expecting a string parameter and so crashed. Therefore the correct commandparameter was
CommandParameter='{Binding Path=EventEntry.Series.Tag, RelativeSource={RelativeSource AncestorType={x:Type ig:EventSpan}}}'
I'm want to use Interaction.Triggers inside a ContentPresenter, but for some reasons, the event doesn't get fired.
If I change ContentPresenter against ContentControl, the event binding works as expected.
<DataTemplate x:Key="MapPictureTemplate">
<Grid Width="80" Height="80" x:Name="Grid">
<Border
Background="{Binding Thumbnail, Converter={StaticResource StreamToImageBrushConverter}}"
CornerRadius="40">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<i:InvokeCommandAction Command="{Binding Source={StaticResource Locator}, Path=Main.ImageTappedCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Border>
</Grid>
</DataTemplate>
and the ContentControl creation in code behind:
var content = new ContentPresenter()
{
Content = this,
ContentTemplate = Application.Current.Resources["MapPictureTemplate"] as DataTemplate
};
I'm trying to bind the SelectedItem to a View. But the view is not able to access the viewmodel when it is inside the Resources block.
When the datacontext is re-assigned to the children, the binding works for textblocks but not for UserControl (NoteView)
Am I missing any Binding?
PFB revised(entire) code and inline comments.
<UserControl x:Class="Konduva.View.NoteSearchView"
<!-- other namespaces here -->
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
DataContext="{Binding NoteSearch, Source={StaticResource Locator}}">
<Grid>
<ListView ItemsSource="{Binding Notes}"
SelectedItem="{Binding SelectedNote}">
<ListView.Resources>
<DataTemplate DataType="{x:Type vm:NoteViewModel}">
<DockPanel>
<TextBlock Text="{Binding Title}" />
<Popup Placement="Right"
PlacementTarget="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}"
IsOpen="{Binding (ListViewItem.IsSelected), RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}"
DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}">
<StackPanel>
<!-- This is working --> <TextBlock Text="{Binding SelectedNote.Title}" />
<!-- This is not working --> <v:NoteView DataContext="{Binding SelectedNote}" />
</StackPanel>
</Popup>
</DockPanel>
</DataTemplate>
</ListView.Resources>
</ListView>
</Grid>
</UserControl>
NoteView:
<Grid>
<TextBlock Text="{Binding Title}" /> // This Text is not displayed
</Grid>
Update 3
Since you're using MvvmLight: in NoteView, try changing
DataContext="{Binding Note, Source={StaticResource Locator}}"
to
<UserControl.Style>
<Style TargetType="UserControl">
<Setter Property="DataContext" Value="{Binding Note, Source={StaticResource Locator}}"/>
</Style>
</UserControl.Style>
Update 2
Encountered a similar problem a few minutes ago which I didn't fully understand so I'll throw in the same solution here to see if it helps. What happends if you change it to this?
<v:NoteView DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type Popup}},
Path=DataContext.SelectedNote}"/>
Update
I'm unable to reproduce this. Try adding this in your NoteView constructor. Do you reach DataContextChangedHandler when you change the selection in the ListView?
public NoteView()
{
InitializeComponent();
DependencyPropertyDescriptor dpd =
DependencyPropertyDescriptor.FromProperty(UserControl.DataContextProperty,
typeof(UserControl));
if (dpd != null)
{
dpd.AddValueChanged(this, new EventHandler(DataContextChangedHandler));
}
}
void DataContextChangedHandler(object sender, EventArgs e)
{
MessageBox.Show("DataContext Changed: " + DataContext);
}
First answer
Your DockPanel will get the NoteViewModel as a DataContext and not the ListView and since this DataContext is inherited by all Childs every child will end up with a NoteViewModel as DataContext. To use the ListView as a DataContext for the Popup you can do this. I'm not sure what the DataContext Binding for the StackPanel does though, so I might be missing something here..
<DataTemplate DataType="{x:Type vm:NoteViewModel}">
<DockPanel>
<TextBlock Text="{Binding Title}" />
<Popup Placement="Right"
PlacementTarget="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}"
IsOpen="{Binding (ListViewItem.IsSelected), RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}"
DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}">
<StackPanel>
<TextBlock Text="{Binding SelectedNote.Title}" />
<StackPanel>
<v:NoteView DataContext="{Binding SelectedNote}"/>
</StackPanel>
</StackPanel>
</Popup>
</DockPanel>
</DataTemplate>
Instead of inserting a NoteView directly and binding the DataContext, use a ContentPresenter:
<ContentPresenter Content="{Binding SelectedNote}>
<ContentPresenter.ContentTemplate>
<DataTemplate>
<v:NoteView />
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>