How do i trigger the SourceUpdate of my wpf listview?
This is my xaml
<ListView DataContext="{StaticResource vmInstance}" SelectedItem="{Binding selectedItem}" BorderBrush="Beige" BorderThickness="1" ItemsSource="{Binding lstExternal}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged" >
<cmd:EventToCommand Command="{Binding Path=ItemChanged}"
PassEventArgsToCommand="True" />
</i:EventTrigger>
<i:EventTrigger EventName="SourceUpdated">
<cmd:EventToCommand Command="{Binding Path=SourceUpdated}"
PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListView.View >
</ListView.View>
</ListView>
ViewModel:
public static RelayCommand SourceUpdated { get; set; }
//on initialize
SourceUpdated = new RelayCommand(SourceUpdateEvent);
public void SourceUpdateEvent()
{
Console.WriteLine("Updated");
}
Why does SourceUpdateEvent doesn't run?
Am I using the wrong event?
Thank you
want to execute a method when the itemsource of the listview is changed or updated
Then bind the ItemsSource property of the ListView to a source property of your view model
<ListView ItemsSource="{Binding YourCollection}" ...>
...and invoke your command in the setter of this source property:
private ObservableCollection<YourType> _sourceCollection;
public ObservableCollection<YourType> SourceCollection
{
get { return _sourceCollection; }
set
{
_sourceCollection = value;
RaisePropertyChanged();
SourceUpdated.Execute(null);
}
}
This is the (only) correct way to solve this using the MVVM pattern.
Related
So I use the Autosuggestionbox of the ModernWPF Toolkit and was trying to get to handle the "QuerySubmitted" event from it via the MVVM way. Here's what I have
<ui:AutoSuggestBox x:Name="TextBox"
Text="{Binding TextBoxID, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
ItemsSource="{Binding Path= TextBoxCollection}"
>
<i:Interaction.Triggers>
<i:EventTrigger EventName="QuerySubmitted" >
<i:InvokeCommandAction Command ="{Binding QuerySubmit}" CommandParameter="{Binding ElementName=TextBox}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ui:AutoSuggestBox>
Heres my ViewModel
public ICommand textBox
public ICommand QuerySubmit
{
get
{
if(textBox== null)
{
///Do some stuff when event fires
}
return textBox;
}
}
and for the namespace of i its
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
But it doesn't seem to work so far. Any guesses on why and how to fix it?
To add, I tried switching it to a different event (MouseDoubleClick) and it works, so I think it's about the event of the querysubmit itself.
I would like to refactor my code a bit with Propertychanged.Fody as shown on this page http://www.mutzl.com/tag/mvvm-light/
Normal code:
private string _platformSelectedItem;
public string PlatformSelectedItem
{
get { return _platformSelectedItem; }
set
{
if (_platformSelectedItem == value) return;
_platformSelectedItem = value;
// Perform any pre-notification process here.
GetData();
RaisePropertyChanged();
}
}
to
public string PlatformSelectedItem {get; private set}
The property is bounded to a Comboxbox and the values for the Combobox are dynamic based on another combobox, therefore I have my Method GetData().
<ComboBox ItemsSource="{Binding Platforms}" SelectedItem="{Binding PlatformSelectedItem, Mode=TwoWay}" Grid.Column="1" Grid.Row="2" Height="20" Grid.ColumnSpan="2" Margin="0,3,15.667,3"/>
If I refactor my code to autoproperties the method must be executed by click / open of the combobox.
Should I use a eventtrigger with command our is a more simpler way possible?
Based on the thread can we use <i:Interaction.Triggers> in WPF MVVM (not in Silverlight)
My final solution looks:
ViewModel:
Properties area:
public RelayCommand SelectionChangedCommand { get; private set; }
Constructor:
SelectionChangedCommand = new RelayCommand(Update);
Method area:
private void Update()
{
GetData();
}
In my UI then:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
<ComboBox ItemsSource="{Binding Platforms}" SelectedItem="{Binding PlatformSelectedItem, Mode=TwoWay}" Grid.Column="1" Grid.Row="2" Height="20" Grid.ColumnSpan="2" Margin="0,3,15.667,3">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectionChangedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
I am trying to bind a click on button event in WPF to a command defined in a View Model, here is how I am doing that for now :
In the xaml code :
<Grid>
<Button Content="Module A" Background="Green" FontWeight="Bold">
<i:Interaction.Triggers>
<i:EventTrigger EventName="click">
<i:InvokeCommandAction Command="{Binding ChargeModuleDCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
and in the ViewModel class :
class ModuleAViewModel
{
public DelegateCommand<object> ChargeModuleDCommand { get; set; }
public ModuleAViewModel()
{
ChargeModuleDCommand = new DelegateCommand<object>(LaunchDModule);
}
private void LaunchDModule(object parm)
{
Console.WriteLine("I am in the function");
}
}
but it does not work. I've tried to do it as specified in this question : How to trigger ViewModel command for a specific button events
but it does not work either.
Is there any way that I can make it work ?
<Button
Command="{Binding ChargeModuleDCommand}"
Content="Module A"
Background="Green"
FontWeight="Bold"
/>
If ModuleAViewModel is the Button's DataContext, that should work.
I have a simple list view with gridview to display each row.
I added a key binding for delete which is working fine.
<ListView.InputBindings>
<KeyBinding Key="Delete" Command="{Binding Path=DeleteKeyCommand}" CommandParameter="{Binding ElementName=DatabasesLstVw, Path=SelectedItem}"/>
</ListView.InputBindings>
But when I add a Mousebinding for LeftDoubleClick to edit its not firing the command.
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding Path=LeftDoubleClickCommand}" CommandParameter="{Binding ElementName=DatabasesLstVw, Path=SelectedItem}" />
After spending the last two hours trying to figure it out the only thing I have come up with is that its firing the double click on the entire list view and not the listview item???
How do I get double click edit to work on one row in my list view? I am using MVVM I don't want to break that so I cant use code behind to hack it. There must be a way to map the command back to my view model.
Update more code:
<ListView x:Name="DatabasesLstVw" ItemsSource="{Binding Path=ClientDetails.Databases}" ItemContainerStyle="{StaticResource alternatingStyle}" AlternationCount="2" Grid.Row="2" Grid.ColumnSpan="4" VerticalAlignment="Top" >
<ListView.InputBindings>
<KeyBinding Key="Delete" Command="{Binding Path=DeleteKeyCommand}" CommandParameter="{Binding ElementName=DatabasesLstVw, Path=SelectedItem}"/>
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding Path=LeftDoubleClickCommand}" CommandParameter="{Binding ElementName=DatabasesLstVw, Path=SelectedItem}" />
</ListView.InputBindings>
As the referenced answer is missing some code, this is how it should be:
public class AddToInputBinding
{
public static System.Windows.Input.InputBinding GetBinding(DependencyObject obj)
{
return (System.Windows.Input.InputBinding)obj.GetValue(BindingProp);
}
public static void SetBinding(DependencyObject obj, System.Windows.Input.InputBinding value)
{
obj.SetValue(BindingProp, value);
}
public static readonly DependencyProperty BindingProp = DependencyProperty.RegisterAttached(
"Binding", typeof(System.Windows.Input.InputBinding), typeof(AddToInputBinding), new PropertyMetadata
{
PropertyChangedCallback = (obj, e) =>
{
((UIElement)obj).InputBindings.Add((System.Windows.Input.InputBinding)e.NewValue);
}
});
}
Then, in your XAML, you would do something like this:
<Window x:Class="WpfApplication.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<ResourceDictionary>
<Style TargetType="ListViewItem">
<Setter Property="local:AddToInputBinding.Binding">
<Setter.Value>
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding DataContext.ItemDoubleClick,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}}"
CommandParameter="{Binding}"/>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Window.Resources>
<Grid>
<ListView ItemsSource="{Binding Patients}">
<ListView.View>
<GridView>
<GridViewColumn Header="Test" />
</GridView>
</ListView.View>
</ListView>
</Grid>
In your viewModel, the command definition would be like this:
RelayCommand<string> _ItemDoubleClick;
public ICommand ItemDoubleClick
{
get
{
if (_ItemDoubleClick == null)
{
_ItemDoubleClick = new RelayCommand<string>(this.ItemDoubleClickExecuted,
param => this.ItemDoubleClickCanExecute());
}
return _ItemDoubleClick;
}
}
private bool ItemDoubleClickCanExecute()
{
return true;
}
private void ItemDoubleClickExecuted(string item)
{
//In item you've got the text of double clicked ListViewItem
}
Note that in this sample, the ListView binded ObservableCollection is of type string. If this was other type, you should change the types in the ICommand definitions. Don't forget also to set the Window DataContext to your ViewModel.
Hope this is clearer now.
I want to set command parameter to currently selected item on a ListBox.
XAML:
<!--<ListBox ItemsSource="{Binding Places}" SelectedItem="{Binding SelectedPlace, Mode=TwoWay}">-->
<ListBox ItemsSource="{Binding Places}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<i:InvokeCommandAction Command="{Binding ListBoxClick}" CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemTemplate>
<DataTemplate>
(...)
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
C# (part of ViewModel code exposing the ListBoxClick command)
public RelayCommand ListBoxClick { get; set; }
ListBoxClick = new RelayCommand((o) => {
//model is always null
var model = o as BasicModel;
SelectedPlace = model;
});
I added appropriate references, and namespace:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
The problem is that in action called by RelayCommand object the o parameter is always null.
UPDATE
C# code for SelectedPlace property
public BasicModel SelectedPlace {
get {
return _selectedPlace;
}
set {
_selectedPlace = value;
RaisePropertyChanged("SelectedPlace");
}
}
When I use this:
<ListBox ItemsSource="{Binding Places}" SelectedItem="{Binding SelectedPlace, Mode=TwoWay}">
everything works fine if I click ListBoxItem for the first time, but when I click on a selected ListBoxItem nothing happens, because selection doesn't change. I need to be able to detect item click in both situations.
I figured out an ugly way to achieve my goal.
XAML
<ListBox ItemsSource="{Binding Places}" SelectedItem="{Binding SelectedPlace, Mode=TwoWay}">
C# (ViewModel)
private bool _placeSelected;
public BasicModel SelectedPlace {
get {
return _selectedPlace;
}
set {
_placeSelected = true;
_selectedPlace = value;
RaisePropertyChanged("SelectedPlace");
}
}
ListBoxClick = new RelayCommand((o) => {
if (!_placeSelected) {
SelectedPlace = _selectedPlace;
}
else {
_placeSelected = false;
}
});
This way RaisePropertyChanged("SelectedPlace"); will be called in both cases.
Try this:
<ListBox ItemsSource="{Binding Places}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<i:InvokeCommandAction Command="{Binding ListBoxClick}"
CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType={
x:Type ListBox}}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemTemplate>
<DataTemplate>
(...)
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If that doesn't work, try changing the Binding to this:
CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource Self}}"
UPDATE >>>
Oh sorry, I didn't see that you were using Windows Phone 7. As an alternative, try adding a property into your code behind/view model that binds to the ListBox.SelectedItem property:
<ListBox ItemsSource="{Binding Places}" SelectedItem="{Binding SelectedItem}" ... />
Then you should be able to do this:
ListBoxClick = new RelayCommand(() => {
SelectedPlace = SelectedItem;
});
UPDATE 2 >>>
I don't know if Windows Phone 7 supports the Binding.ElementName property, but if it does, try this:
<ListBox Name="ListBox" ItemsSource="{Binding Places}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<i:InvokeCommandAction Command="{Binding ListBoxClick}"
CommandParameter="{Binding SelectedItem, ElementNameListBox}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemTemplate>
<DataTemplate>
(...)
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>