I have an employee table I filtered from Location with a combobox in WPF MVVM.
like that:
in xaml:
<ComboBox Grid.Column="2" ItemsSource="{Binding Locations}" SelectedItem="{Binding SelectedLocation}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding LocationFilterCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
In ViewModel:
Locations = new ObservableCollection<string>()
{ "All","A","B"};
and in LocationFilterCommand
#region LocationFilterCommand
private DelegateCommand _locationFilterCommand;
public DelegateCommand LocationFilterCommand
{
get { return _locationFilterCommand ?? (_locationFilterCommand = new DelegateCommand(CanLocationFilter, LocationFilter)); }
}
private bool CanLocationFilter()
{
return true;
}
private void LocationFilter()
{
ParticularEntries = ParticularEntries.Where(p =>p.Region.Location==_selectedLocation);
}
I dont have problem with when I select A location or when I select B location they comes to screen.But I dont know how to take all values together with "All" item in combobox?
Hint:All is not a location type.All need all locations employee together come to screen.But I dont know how to this filter ?
thank you for all your helps.
Related
I have a DataGrid with long time loading.
I want put a BusyIndicator for the time to wait.
I have declared a property "IsBusy" in my ViewModel, the BusyIndicator is raised on it.
If I declare the property with "true" by default, the BusyIndicator does display good => OK.
If I declare it to be "false", the BusyIndicator is hidden => OK.
But, if I set the value by triggers in XAML, the property is well set, but the BusyIndicator doesn't appear.
ViewModel:
public bool IsBusy
{
get { return _IsBusy; }
set { _IsBusy = value; RaisePropertyChanged(nameof(IsBusy)); }
}
private void SetBusy(bool obj)
{
IsBusy = obj;
}
XAML:
<xctk:BusyIndicator Name="BusyBar" IsBusy="{Binding IsBusy, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" BusyContent="Traitement en cours. veuillez patienter..." />
<ComboBox x:Name="cbbSchEtt" ...>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SetBusyCommand}" CommandParameter="True"/>
<ei:CallMethodAction MethodName="LoadTableau" TargetObject="{Binding ElementName=ucTabBord}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
Same thing if I set it by code behind (m is my ViewModel):
private void LoadTableau()
{
m.IsBusy = true;//Mouse.OverrideCursor = Cursors.Wait;
.....
m.IsBusy = false;
}
For information, if I don't set it to false at the end of LoadTableau(), the BusyIndicator is displayed well.
Any idea ?
Maybe a simple question here, I tried to set PassEventArgsToCommand=True on MvxEventToCommand. But found no benefit.
The event/command gets fired on my ViewModel for "True" and for "False".This is OK, no complains here. But how do I access the EventArgs on the ViewModel?
Also using MvxWithArgsEventToCommand (which sets PassEventArgsToCommand to true) had no effect. I looked online and in NPlus1DaysOfMvvmCross samples but found no hints. I'm using WPF. Any help is much appreciated.
XAML:
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<commands:MvxEventToCommand Command="{Binding DataContext.MyMandatory_SelectionChangedCommand,
Source={x:Reference MyView}}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type syncfusion:ComboBoxAdv}, Mode=FindAncestor}}"
PassEventArgsToCommand="True"
/>
</i:EventTrigger>
ViewModel:
public IMvxCommand MyMandatory_SelectionChangedCommand
{
get
{
return new MvxCommand<Object>(e => MyMandatory_Changed(e));
}
}
public void MyMandatory_Changed(Object e)
{
if (e != null && e is ComboBoxAdv)
{
ComboBoxAdv cbo = (ComboBoxAdv)e;
…Further code
}
}
I want to implement a checkbox which functions as a select-all / unselect-all checkbox but I am getting some problems with the binding. I am not really new to XAML and WPF so it is a mistery to me why my code is not working. I hope you can help. This is what I am doing:
First of all, I use MVVMLight and the event-to-command tags.
My view is called SetupView.xaml and my view-model is called SetupViewModel.cs
public class SetupViewModel : ViewModelBase
{
private List<FilterOptions> m_informationToShow;
private FilterOptions m_currentSelection;
public List<FilterOptions> InformationToShow
{
get { return m_informationToShow; }
set
{
m_informationToShow = value;
RaisePropertyChanged("InformationToShow");
RaisePropertyChanged("InformationToShowCount");
}
}
public FilterOptions CurrentSelection
{
get { return m_currentSelection; }
set
{
m_currentSelection = value;
RaisePropertyChanged("CurrentSelection");
}
}
}
The FilterOptions-object is my model object. Because you will need some of it it to understand the problem, here it show the part you need to understand the problem:
public class FilterOptions
{
private string m_projectName;
private BugsFilter m_bugsFilter;
private BuildsFilter m_buildsFilter;
private ChangeSetsFilter m_changeSetsFilter;
private ProgressInfoFilter m_progressInfoFilter;
private RisksFilter m_risksFilter;
private bool m_projectHealthFilter;
public bool AllFilterValues
{
get
{
if (m_bugsFilter.AtLeastOneFieldEnabled() ||
m_buildsFilter.AtLeastOneFieldEnabled() ||
m_changeSetsFilter.AtLeastOneFieldEnabled() ||
m_progressInfoFilter.AtLeastOneFieldEnabled() ||
m_risksFilter.AtLeastOneFieldEnabled() ||
m_projectHealthFilter
)
{
return true;
}
else
{
return false;
}
}
set
{
if (value == false)
{
m_bugsFilter.NoInformation();
m_buildsFilter.NoInformation();
m_changeSetsFilter.NoInformation();
m_progressInfoFilter.NoInformation();
m_risksFilter.NoInformation();
m_projectHealthFilter = false;
}
else
{
m_bugsFilter.CompleteInformation();
m_buildsFilter.CompleteInformation();
m_changeSetsFilter.CompleteInformation();
m_progressInfoFilter.CompleteInformation();
m_risksFilter.CompleteInformation();
m_projectHealthFilter = true;
}
}
}
I will proceed with my view:
<UserControl.Resources>
<viewModels:SetupViewModel x:Key="thisViewModel"></viewModels:SetupViewModel>
<DataTemplate x:Key="ProjectEntryTemplate">
<Border Margin="75,20,5,0">
<CheckBox Name="naam" Content="{Binding ProjectName}"
FontFamily="Segoe UI"
FontWeight="Light"
FontSize="24"
IsChecked="{Binding AllFilterValues}"
DataContext="{Binding}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<mvvm:EventToCommand Command="{Binding ProjectListItemCheckedChanged, Source={StaticResource thisViewModel}}"
PassEventArgsToCommand="True"/>
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<mvvm:EventToCommand Command="{Binding ProjectListItemCheckedChanged, Source={StaticResource thisViewModel}}"
PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
</Border>
</DataTemplate>
</UserControl.Resources>
As you can see, I have a datatemplate which I am using in a listbox:
<ListBox ItemsSource="{Binding InformationToShow}"
ItemTemplate="{StaticResource ProjectEntryTemplate}"
SelectedIndex="0"
BorderThickness="0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<mvvm:EventToCommand Command="{Binding SelectionListboxChanged}"
PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
Besides from that, I have in the same window, in another grid on the right side, a lot of checkboxes. They all correspond to a given filter from the FilterOptions object. This is what I am doing in my view:
<StackPanel Orientation="Vertical"
Margin="0,5,0,5">
<CheckBox Name="activeBugs" Content="Active bugs"
FontFamily="Segoe UI"
FontWeight="Light"
FontSize="22"
IsChecked="{Binding CurrentSelection.BugsFilter.ActiveBugs}">
</CheckBox>
<CheckBox Name="resolvedBugs" Content="Resolved bugs"
FontFamily="Segoe UI"
FontWeight="Light"
FontSize="22"
IsChecked="{Binding CurrentSelection.BugsFilter.ResolvedBugs}"/>
<CheckBox Name="bugTrend" Content="Bug trend"
FontFamily="Segoe UI"
FontWeight="Light"
FontSize="22"
IsChecked="{Binding CurrentSelection.BugsFilter.BugTrend}"/>
</StackPanel>
Last but not least, this are the command functions which I have in my view-model:
RelayCommand m_selectionChanged;
public ICommand SelectionListboxChanged
{
get
{
if (m_selectionChanged == null)
m_selectionChanged = new RelayCommand(param => SelectionListboxChangedExec(param), param => true);
return m_selectionChanged;
}
}
private void SelectionListboxChangedExec(object param)
{
SelectionChangedEventArgs e = (SelectionChangedEventArgs)param;
ListBox b = (ListBox)e.Source;
CurrentSelection = (FilterOptions)b.SelectedItem;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
RelayCommand m_projectCheckedChanged;
public ICommand ProjectListItemCheckedChanged
{
get
{
if (m_projectCheckedChanged == null)
m_projectCheckedChanged = new RelayCommand(param => ProjectListItemCheckedChangedExec(param), param => true);
return m_projectCheckedChanged;
}
}
private void ProjectListItemCheckedChangedExec(object param)
{
RoutedEventArgs e = (RoutedEventArgs)param;
CheckBox checkBox = (CheckBox)e.Source;
FilterOptions dataContext = (FilterOptions)checkBox.DataContext;
if ((bool)checkBox.IsChecked)
dataContext.AllFilterValues = true;
else
{
dataContext.AllFilterValues = false;
}
//var expression = checkBox.GetBindingExpression(ToggleButton.IsCheckedProperty);
//expression.UpdateSource();
}
I really cant find the problem. Is there anyone who can help me?
Your help will be much appreciated !!
Thank you all in advance !
Why do you have to do it with a command? bind the checkbox to a BindingOption class that internally notifies the parent ViewModel, this notification really doesn't belong in the view, but to the view-model.
The ViewModel isn't supposed to know that the view uses a CheckBox.
So what u should do have the individual options have a notifying IsSelected property bound to the CheckBoxes, provide each of them with a reference to the parent ViewModel, and notify the parent when current IsSelected was changed. Doing this in the View, although you can find many way to do it, you're not supposed to, MVVM is about separating view-tasks from viewmodel-tasks.
This is way also gives you control on "Select all", "Deselect all" or "Invert selection" etc.
I have a combobox with rules in a view and it works well, but I want another field of the model from the itemsource to be used to bind to (or as I used it) update another field score.
E.g. if you select rule 1 in the combobox it should update the score field in the view with 1 and if you change the selecteditem to rule 2 it should show 2 in the score field.
My code might be a bit crippled because I experimented 'on the way here' to achieve the desired result, I have a ScoreView with a datagrid which itemsource is scores:
SelectionChangedCommand = new RelayCommand<string>((_score) => SelectedRuleChanged(_score));
private void SelectedRuleChanged(string _score)
{
int _tmpint;
_tmpint = this.SelectedScore.Model.score;
int.TryParse(_score, out _tmpint);
this.SelectedScore.Model.score = _tmpint;
//Todo weghalen lokale rules collectie en get_rules voids
//get_rules_by_ruleset(this.SelectedMatch.Model.ruleset);
}
<ComboBox
Height="23" HorizontalAlignment="Left"
Name="cmbRules" VerticalAlignment="Top" Width="100" ItemsSource="{Binding MatchVM.Rules}" SelectedValue="{Binding Model.ruleid, Mode=TwoWay}"
DisplayMemberPath="Model.name" SelectedValuePath="Model.ruleid">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand Command="{Binding MainScore.SelectionChangedCommand, Mode=OneWay,
Source={StaticResource Locator}}" CommandParameter="{Binding Model.score}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
I try to pass the elements selecteditem (which I bound to model.score) as a command parameter..
Maybe I should use the selecteditem of MatchVMRule but the score text field is bound to the Scores ViewModel instead of the Rules ViewModel?
Thanks in advance,
Mike
UPDATE SOLVED
I finally solved it by creating two separate props rules collection and selected rule in my MainScoreViewModel.
I got rid of the eventocommand and handled the update of the score field in my Score Model based on the score of the Rule Model in the setter of the SelectedRule:
/// <summary>
/// Gets the SelectedRule property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public RuleViewModel SelectedRule
{
get
{
return _selectedRule;
}
set
{
if (_selectedRule == value)
{
return;
}
_selectedRule = value;
this.SelectedScore.Model.score = this.SelectedRule.Model.score;
RaisePropertyChanged(SelectedRulePropertyName);
}
}
<ComboBox
Height="23" HorizontalAlignment="Left"
Name="cmbRules" VerticalAlignment="Top" Width="100" ItemsSource="{Binding ScoreVM.Rules,
Mode=TwoWay}" SelectedValue="{Binding Model.ruleid, Mode=TwoWay}"
DisplayMemberPath="Model.name" SelectedValuePath="Model.ruleid" SelectedItem="{Binding
ScoreVM.SelectedRule, Mode=TwoWay}">
</ComboBox>
What about using the PropertyChange notification on your ViewModel to handle the SelectionChanged event instead of trying to handle it from the View?
public ParentViewModel()
{
this.Model.PropertyChanged += Model_PropertyChanged;
}
void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "ruleid":
this.SelectedScore.Model.Score = Model.Score;
}
}
If you have a Silverlight Toolkit NumericUpDown control binded to a MVVM property and a RelayCommand trigger set (any event), the command is called before NumericUpDown changes MVVM property value. This means, you can not use the new (changed) value with you method/action/command...
XAML:
<inputToolkit:NumericUpDown x:Name="testNum" Value="{Binding RegisterForm, Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="ValueChanged">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding DoSomethingCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</inputToolkit:NumericUpDown>
MVVM (C#):
DoSomethingCommand = new RelayCommand(() =>
{
OtherRegisterForm = RegisterForm;
});
In this case, if you have v value 0 and you input a new value 123 in NumericUpDown control it triggers the "DoSomethingCommand" before "RaisePropertyChange" event on MVVM property.
"OtherRegisterForm" would be 0 and not 123.
Is there a way to make this work?
oh boy, wasn't easy but here u are :
xaml part :
<toolkit:NumericUpDown Value="{Binding SomeNumber}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="ValueChanged">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding MyCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</toolkit:NumericUpDown>
and cs code :
public class MainViewModel : ViewModelBase
{
public double SomeNumber { get; set; }
public MainViewModel()
{
SomeNumber = 10;
MyCommand = new RelayCommand<RoutedPropertyChangedEventArgs<double>>(myActionMethod);
}
public RelayCommand<RoutedPropertyChangedEventArgs<double>> MyCommand { get; set; }
public void myActionMethod(RoutedPropertyChangedEventArgs<double> arg)
{
MessageBox.Show(arg.NewValue.ToString());
}
}
hope that helps, Arek