Why ComboBox SelectionChanged event fire when we changed value of combobox in WPF?
<telerik:RadComboBox Name="onClockComboBox" Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2" Width="200" Height="30" StaysOpenOnEdit="True" IsSynchronizedWithCurrentItem="True" OpenDropDownOnFocus="True"
ItemsSource="{Binding TravelOtherModel.OnClockOptionListCollection,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center"
DisplayMemberPath="OptionName" SelectedValuePath="RowNo" IsFilteringEnabled="True" IsEditable="True" Margin="80,3,0,0">
<ie:Interaction.Triggers>
<ie:EventTrigger EventName="SelectionChanged">
<ie:InvokeCommandAction Command="{Binding OnClockComboBoxSelectedItemChangedCommand}" CommandParameter="{Binding ElementName=onClockComboBox}" >
</ie:InvokeCommandAction>
</ie:EventTrigger>
</ie:Interaction.Triggers>
</telerik:RadComboBox>
SelectionChanged event Code is -
public void OnClockComboBoxSelectedItemChangedCommand_Event(object obj)
{
try
{
RadComboBox onClockComboBox = obj as RadComboBox;
var item = onClockComboBox.SelectedItem as OnClockOption;
string s= onClockComboBox.SelectedValue.ToString();
onClockComboBox.SelectedValue = "0";
}
catch (Exception ex)
{
}
}
When we set default selected value by below code then its again firing SelectionChanged event why?
onClockComboBox.SelectedValue = "0";
When we set default 'select' value by below code then its again firing
selection Changed event why?
Because it should, otherwise how will you get notified if the combo box is reset. Assuming your selected value is bound to load some other control. It would require to know if the selection has changed even for the default value.
Related
I have a datagridview populated with items and I am using a SelectionChanged event to populate textboxes from that data when selected.
If I make a selection, everything works. If I click elsewhere in the App and then come back to click the SelectionChanged event again on the same item - it doesn't work.
According to MSDN:
"This event occurs whenever there is a change to a selection."
MSDN SelectionChangedEvent
So it appears that despite clicking elsewhere, resetting the Textboxes - the selected item is not changing as the SelectionChanged event no longer triggers - click on another item and it works, click back again and it works - but click on it, reset textboxes, click it again - nothing happens, this includes clicking in the datagridview itself in a blank area.
XAML:
<DataGrid x:Name="TimeView" Grid.Row="1" Grid.Column="3"
Grid.ColumnSpan="3" Grid.RowSpan="4" Margin="10 50 10 10"
CanUserAddRows="False" Visibility="{Binding StartTiming}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cal:ActionMessage MethodName="SelectedTimeChangeEvent">
<cal:Parameter Value="$eventArgs" />
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
ViewModel
public void SelectedTimeChangeEvent(SelectionChangedEventArgs e)
{
foreach (TimeData addedRow in e.AddedItems)
{
TbID = addedRow.ID;
TbDate = addedRow.Date;
TbStartTime = addedRow.StartTime;
TbDescription = addedRow.Description;
}
}
Since I am using MVVM and Caliburn, TimeView is connected to an ICollection, which is in turn connected to an ObservableCollection:
private ObservableCollection<TimeData>? _timeCollection;
public ObservableCollection<TimeData>? TimeCollection
{
get { return _timeCollection; }
set
{
_timeCollection = value;
NotifyOfPropertyChange(() => TimeCollection);
}
}
private ICollectionView? _timeView;
public ICollectionView? TimeView
{
get { return _timeView; }
set
{
_timeView = value;
NotifyOfPropertyChange(() => TimeView);
}
}
There is a work around, which is the following after populating the Textboxes:
TimeView = null;
TimeView = CollectionViewSource.GetDefaultView(TimeCollection);
This works, but I thought that there might be a "deselect" option that would be better than repopulating every time a selection is made, one of my Datagrids contains 15,000 items, and it is still instant, but seems overkill to populate it every time a selection is made.
i would recommend bindings, they automaticly reset when nothing is selected
<DockPanel>
<StackPanel DataContext="{Binding SelectedTime}" DockPanel.Dock="Left">
<TextBlock Text="{Binding ID}"/>
<TextBlock Text="{Binding Date}"/>
<TextBlock Text="{Binding StartTime}"/>
<TextBlock Text="{Binding Description}"/>
</StackPanel>
<DataGrid ItemsSource="{Binding TimeView}" SelectedItem="{Binding SelectedTime}">
...
</DataGrid>
</DockPanel>
public TimeData SelectedTime
{
get { return _selectedTime; }
set
{
_selectedTime = value;
NotifyOfPropertyChange(() => SelectedTime);
}
}
also there is this neet feature
protected virtual void SetValue<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
field = value;
OnPropertyChanged(propertyName);
}
so you can write
set { SetValue(ref _selectedTime, value) }
My problem is that after I select a item in the ComboBox, the first item or "default" item of the combobox stays empty but if I click the combobox the values beneath show up are selectable etc. but I want the clicked one to show in the "default/first" place.
What I tried so far
XAML:
<ComboBox Margin="55,0,0,10" Height="20" Width="145" VerticalAlignment="Center" HorizontalAlignment="Left"
ItemsSource="{Binding TabItems, Source={StaticResource MainWindowViewModelRefactored}, Mode=TwoWay}"
SelectedItem="{Binding SelectedItem, Source={StaticResource MainWindowViewModelRefactored}, Mode=TwoWay}"
DisplayMemberPath="Header">
</ComboBox>
Property:
public TabItem SelectedItem {
get {
return _selectedItem;
}
set {
UpdateTCVCollection(value);
_selectedItem = value;
NotifyPropertyChanged("SelectedItem");
}
}
If I open up the combobox the selecteditem is highlighted, but I also want it to be shown in the "first place" when the ComboBox is closed.
You can add a method when the index has changed, then remove the item that the user selected and add it at the begining.
I've set the value of Sorted to false because that way the value you selected won't be reorganized in your ComboBox.
private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e) {
RadItem selectedItem = ComboBox1.SelectedItem as RadItem;
if (selectedItem != null) {
ComboBox1.Items.Remove(selectedItem);
ComboBox1.Items.Sorted = true;
ComboBox1.Items.Sorted = false;
ComboBox1.Items.Insert(0, selectedItem);
ComboBox1.Text = selectedItem.Text;
}
}
Add the UpdateSourceTrigger to your Combobox.
UpdateSourceTrigger=PropertyChanged
Example:
<ComboBox Margin="55,0,0,10" Height="20" Width="145" VerticalAlignment="Center" HorizontalAlignment="Left"
ItemsSource="{Binding TabItems, Source={StaticResource MainWindowViewModelRefactored}, Mode=TwoWay}"
SelectedItem="{Binding SelectedItem, Source={StaticResource MainWindowViewModelRefactored}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Header">
</ComboBox>
Have a look to this MSDN link
That should help you with your problem.
Greetings
I have a listview in WPF in an MVVM/PRISM app which may contain 1-to-many elements. When the listview contains only 1 element, and I select it, I cannot subsequently reselect it even though I set the SelectedIndedx value to -1. Worse, if I make the app update the listview with a different single element, I can't select that one either. The only way I can achieve selection of an item when it is the only item in the listview is to make the app display multiple items and select something other than the first. Then, when I make the app display a listview containing a single item, I can select it again - but only once.
In those cases where I cannot select the single item in the listview, the servicing routine never fires.
I tried implementing a XAML suggestion I found here using "Listview.Container.Style" and the IsSelected property, but that did not work.
My listview is fairly straightforward:
<ListView Name="lstEditInstance"
Grid.Row="5"
ItemsSource="{Binding Path=InstanceList,Mode=TwoWay}"
Width="488"
FontFamily="Arial" FontSize="11"
HorizontalAlignment="Left" VerticalAlignment="Stretch"
Margin="10,96,0,28"
SelectedIndex="{Binding Path=InstanceSelectedIndex}">
</ListView>
The servicing routine is:
private void OnInstanceSelectedIndexChanged()
{
// Handle case where user hits Enter without making a selection:
if (_instanceIndex == -1) return;
// Get the instance record for the row the user clicked on as a
// ResourceInstance class named "InstanceRecord".
InstanceRecord = _instanceList[_instanceIndex];
_instanceNumber = InstanceRecord.Instance;
FormInstName = InstanceRecord.InstName;
FormInstEnabled = InstanceRecord.Enabled;
FormInstState = InstanceRecord.InitialState;
FormInstIPAddress = InstanceRecord.IPAddress;
FormInstPort = InstanceRecord.Port.ToString();
FormInstSelectedURL = InstanceRecord.UrlHandler;
} // End of "OnResourceSelectedIndexChanged" method.
"InstanceList" is an observable collection.
I'd appreciate some suggestions. Thanks in advance for any help.
In a MVVM scenario, I'd use a ViewModel that contains the selected item instead:
class MyViewModel {
private IList<Item> instanceList= new List<Item>();
public IList<Item> List
{
get {return list; }
set {
list = value;
RaisePropertyChanged(() => List);
}
}
private Item selectedItem;
public Item SelectedItem {
get {return selectedItem;}
set {
selectedItem = value;
RaisePropertyChanged(() => SelectedItem);
}
}}
And the XAML:
<ListView Name="lstEditInstance"
Grid.Row="5"
ItemsSource="{Binding Path=InstanceList}"
Width="488"
FontFamily="Arial" FontSize="11"
HorizontalAlignment="Left" VerticalAlignment="Stretch"
Margin="10,96,0,28"
SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}}">
Notice that observableCollection is not required unless you have to modify the list items, in the same way the binding should be the default one for the list.
The SelectedItem / SelectedIndex should be TwoWay or Onewaytosource, the latter if you think you don't need to change the selectedItem programmatically
The service routine should be called from the ViewModel
EDIT:
your code of the service routine should be placed there:
set {
selectedItem = value;
// your code
RaisePropertyChanged(() => SelectedItem);
}
Another valid approach is to use Blend on XAML, by invoking a command on changed index and process under the ViewModel.
To do this, first add reference to System.Windows.Interactivity in your project and in XAML add
xmlns:interactivity="http://schemas.microsoft.com/expression/2010/interactivity
Then modify ListView with the following:
<ListView Name="lstEditInstance"
Grid.Row="5"
ItemsSource="{Binding Path=InstanceList}"
Width="488"
FontFamily="Arial" FontSize="11"
HorizontalAlignment="Left" VerticalAlignment="Stretch"
Margin="10,96,0,28"
SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}}">
<interactivity:Interaction.Triggers>
<interactivity:EventTrigger EventName="SelectionChanged">
<interactivity:InvokeCommandAction Command="{Binding YourCommand}"
CommandParameter="{Binding YourCommandParameter}" />
</interactivity:EventTrigger>
</interactivity:Interaction.Triggers>
I want to raise event using MouseLeftButtonDown by clicking on a date in Calendar Control. But it is not raised until I click outside of this component.
Here is the xaml code:
<Controls:BasicCalendar Grid.Row="0"
x:Name="DemoCalendar"
DisplayDate="{Binding Path=DisplayDate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
HighlightedDateText="{Binding HighlightedDateText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="0,0,0,0"
DateHighlightBrush="Gold">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<cal:ActionMessage MethodName="CalendarSelectDateEvent">
<cal:Parameter Value="{Binding ElementName=DemoCalendar, Path=SelectedDate}" />
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</Controls:BasicCalendar>
Here is the event which I want to raise after clicking on some date in calendar:
public void CalendarSelectDateEvent(DateTime selectedDate)
{
this.ActualCalendarEvents = this.CalendarEvents.Where(x => x.Date >= selectedDate).ToList();
var a = this.ActualCalendarEvents;
this.ActualCalendarEvents = null;
NotifyOfPropertyChange(() => ActualCalendarEvents);
this.ActualCalendarEvents = a;
NotifyOfPropertyChange(() => ActualCalendarEvents);
}
When I tried to use Click event instead of MouseLeftButtonDown the Calendar Control was automatically handling it without firing CalendarSelectDateEvent. Is there a way to fire both events? (For Calendar Control selecting and highlighting the dat and for me CalendarSelectDateEvent)
I already figured it out. It was really easy in the end. The Calendar Control has property SelectedDate. I just binded SelectedDate to my property SelectedDateChanged in code behind and when the SelectedDate changed I raise the event CalendarSelectDateEvent.
<Controls:BasicCalendar Grid.Row="0"
x:Name="DemoCalendar"
DisplayDate="{Binding Path=DisplayDate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
HighlightedDateText="{Binding HighlightedDateText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="0,0,0,0"
SelectedDate="{Binding SelectedDateChanged}"
DateHighlightBrush="Gold">
</Controls:BasicCalendar>
Like this:
public DateTime SelectedDateChanged
{
get
{
return selectedDateChanged;
}
set
{
this.selectedDateChanged = value;
this.CalendarSelectDateEvent(this.selectedDateChanged);
}
}
I have a Window with ListBox on the left Side and TextBox on the right Side. The Textbox is binding to the Selected Item of the ListBox. The Textbox has a SaveContentCommand.
If you leave the Textbox with Enter or the Tab the SaveContentCommand is executed correct. But if i use the mouse to select something else the selecteditem is changed and then the SaveContentCommand is executed. This means the SaveContentCommand is used on another item.
I have tried to hack something like RenameLastSelectedItem()
But is there a correct/better way?
My List:
<customControls:MyListBox x:Name="UserListBox"
Grid.Row="1"
Grid.Column="0"
ItemsSource="{Binding Users}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Top"
Style="{DynamicResource MyListBoxStyle}"
ItemContainerStyle="{DynamicResource MyListBoxItemUserListStyle}">
My TextBox:
<customControls:MyTextBox x:Uid="textBoxName"
x:Name="textBoxNameOfSelectedItems"
Text="{Binding SelectedItem.Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=true, Mode=TwoWay}"
focus:FocusExtension.IsFocused="{Binding SelectedItem.IsNameFocused, Mode=TwoWay}"
focus:FocusExtension.EnableSelection="True"
UseKeyboardBinding="true"
Style="{DynamicResource MyTextBoxStyle}"
SaveContentCommand="{Binding SelectedItem.UpdateCommand}"
In the set method of the SelectedItem, save the previous item. This code will run when the selected item is changed when selecting a new item with the mouse..
SelectedItem
{get { return _selectedItem;}
set
{
//null check
SaveContent(_selectedItem);
_selectedItem = value;
}
}