With a regular ComboBox I would use the following code to deactivate the Selection Change.
<ComboBox Name="CbbTest" SelectionChanged="CbbTest_SelectionChanged"></ComboBox>
CbbTest.SelectionChanged -= new SelectionChangedEventHandler(CbbTest_SelectionChanged);
However, when my ComboBox is in a DataTemplate I am not able to access the ComboBox by name, and therefore I am not able to turn off the selection changed.
How can deactivate ComboBox CbbTestTwo like in the previous code, but from a DataTemplate in the following code?
<StackPanel>
<DataGrid>
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="CbbTestTwo" SelectionChanged="CbbTestTwo_SelectionChanged"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
Any help in this matter would be appreciated
If I understand correctly, you seek to be able to manipulate your combobox in the SelectionChanged event. You can get your combobox like this:
private void cbTest_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox comboBox = new ComboBox();
if(sender is ComboBox)
{
comboBox = (ComboBox)sender;
}
}
Can now handle it like that :
private void cbTest_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox comboBox = new ComboBox();
if(sender is ComboBox)
{
comboBox = (ComboBox)sender;
}
//Add the treatments you want
comboBox.Items.Clear();
comboBox.ItemsSource = listTest;
}
You might want to use more MVVM like approach which means subscribing directly on events in the code behind of the view is not the best option. In this case you could use a behavior like this.
public class ComboBoxSelectionChangedBehavior : Behavior<ComboBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectionChanged += OnSelectionChanged;
}
private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
// ....
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.SelectionChanged -= OnSelectionChanged;
}
}
And then you can attach this behavior through xaml. Here is a short tutorial on behaviors https://blog.jayway.com/2013/03/20/behaviors-in-wpf-introduction/
Find control inside Listbox.ItemTemplate (WPF C#)
Please refer this link, from the above code snippet, once you will have the combobox instance, you can unsubscribe the event.
Related
Evening all, I've run into an issue with the SelectionChanged (TabControl) event being call before the LostFocus (TextBox) event.
This is a problem since the SelectionChanged is triggered during a tab change, that intern resets the ListView.SelectedIndex (TabControl>TabItem>ListView) to -1.
The textbox uses LostFocus to update/validate it's textbox.text which depend upon the SelectedIndex. The text in the textbox is stored/retrieved from a List<string> and because the index changed, the List happens to go out of bounds.
I've looked around, tired a few things also a "hack-y" approach which didn't really help.
<TabControl SelectionChanged="SelectionChanged_Tab"
<TabItem .../>
<TabItem .../>
</TabControl>
<Grid>
<Label .../>
<TextBox Name="Name" LostFocus="Lost_Focus" .../>
</Grid>
Code:
private void SelectionChanged_Tab(object sender, SelectionChangedEventArgs e)
{
if (e.Source is TabControl)
{
ListView1.SelectedIndex = -1;
ListView2.SelectedIndex = -1;
}
}
private void Lost_Focus(object sender, RoutedEventArgs e)
{
TextBox textbox = sender as TextBox;
int Index = ListView.SelectedIndex;
if (string.IsNullOrEmpty(textbox.Text) || textbox.Text == "0")
{
textbox.Text = "0";
}
switch (textbox.Name)
{
case "Name":
SomeList[Index].AProperty = textbox.Text;
break;
}
}
OK, so after think about the problem from a different perspective, I decided to simple make the TabControl, an Focus-able event and simple make it focus when selection changes:
<TabControl SelectionChanged="SelectionChanged_Tab" Focusable="True"
<TabItem .../>
<TabItem .../>
</TabControl>
Code:
private void SelectionChanged_Tab(object sender, SelectionChangedEventArgs e)
{
if (e.Source is TabControl)
{
ListView2.Focus();
ListView1.SelectedIndex = -1;
ListView2.SelectedIndex = -1;
}
if (ListView2.SelectedIndex == -1)
{
ListView1.Focus();
}
}
I know it's not the most elegant solution (In the process or re-factoring) but this seems to get the job done.
I'm stuck on a strange problem.
I have an AutoCompleteBox in my view
<sdk:AutoCompleteBox x:Name="txtSIA"
Grid.ColumnSpan="1" Grid.Row="1" Grid.Column="1"
SelectedItem="{Binding SIA, Mode=TwoWay, ValidatesOnNotifyDataErrors=True}"
Text="{Binding TextSIA, Mode=TwoWay}"
KeyUp="TxtSIA_KeyUp"
Populating="SIANonSIU_Populating"
Style="{StaticResource AutoCompleteStyle}"
/>
I implemented a field validator that check if its text isn't null or an empty string.
It works pretty well but the tricky part is that I have a button that Reset all my controls values, which code from my viewmodel is:
void BtnReset_OnClick(RoutedEventArgs e)
{
SIA = new SIA();
TextSIA = string.Empty;
BtnGeneralIsEnabled = false;
DataGridSource = null;
}
Whenever I click it and then write in my AutoCompleteBox, the AutoCompleteBox is never empty or null even in my code behind in a key up event listener.
Here are some picture to illustrate my point:
Register to the TextChanged event of the AutoCompleteBox instead of the KeyUp:
"Occurs when the text in the text box portion of the AutoCompleteBox changes."
I found an answer here
To fix that but we have to create a new autocompletebox and override the OnApplyTemplate method.
public class CustomAutoComplete : AutoCompleteBox
{
TextBox mytext;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
mytext = GetTemplateChild("Text") as TextBox;
mytext.TextChanged += new System.Windows.Controls.TextChangedEventHandler(mytext_TextChanged);
}
void mytext_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
this.Text = mytext.Text;
OnTextChanged(new RoutedEventArgs());
}
}
I have list of items in LongListMultiSelector - how to handle a selected item?
My LongListMultiSelector xaml:
<tkit:LongListMultiSelector Name="longlist" SelectionChanged="longlist_SelectionChanged">
<tkit:LongListMultiSelector.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" FontSize="32" Tap="TextBlock_Tap"/>
</DataTemplate>
</tkit:LongListMultiSelector.ItemTemplate>
</tkit:LongListMultiSelector>
TextBlock tap event handler code:
private void TextBlock_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
var itemTapped = (sender as FrameworkElement).DataContext as Book;
}
LongListMultiSelector SelectionChanged event handler code:
private void longlist_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
I found part of solution here, however, The problem if at least one item is selected, then textblockTap event doesn't handle - longlist_SelectionChanged event handles everything. How can i fix that?
Once you are using LongListMultiSelector, the SelectionChanged event is fired when item is added or removed. If you want to perform the action regardless item is added/removed, I've managed to do it like this (for a simle string):
private void longlist_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string selectedItem = String.Empty;
if (e.AddedItems.Count > 0) selectedItem = e.AddedItems[0] as string;
else selectedItem = e.RemovedItems[0] as string;
MessageBox.Show(selectedItem); // do your work
}
It should run while items are selected separately by tapping, but this method will have problems when more items are added/removed at the same time - if you need it, then you should handle this also.
Your XAML DataTemplate.
<DataTemplate x:Key="listItemTemplate">
<StackPanel Orientation="Horizontal" Margin="4,4">
<TextBlock Tap="textblockTap" Margin="0,-7,0,0" Text="{Binding Name}" Style="{StaticResource PhoneTextLargeStyle}"/>
</StackPanel>
</DataTemplate>
In your CS page;
private void textblockTap(object sender, EventArgs e)
{
var file = (TextBlock)sender;
var ContentFile = (string)file.Text;
MessageBox.Show(ContentFile);
}
This example will show you the text of the selected item in the MessageBox.
I have a datagrid, with a combobox column
<DataGridComboBoxColumn x:Name="DataGridComboBoxColumnBracketType" Width="70" Header="Tipo di staffa" SelectedValueBinding="{Binding type, UpdateSourceTrigger=PropertyChanged}">
</DataGridComboBoxColumn>
I want an event that is fired only when the user changes the value into the combobox.
How can I resolve this?
I found a solution to this on CodePlex. Here it is, with some modifications:
<DataGridComboBoxColumn x:Name="Whatever">
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<EventSetter Event="SelectionChanged" Handler="SomeSelectionChanged" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
and in the code-behind:
private void SomeSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var comboBox = sender as ComboBox;
var selectedItem = this.GridName.CurrentItem;
}
And the xaml code provided by #kevinpo from CodePlex and help from David Mohundro's blog, programatically:
var style = new Style(typeof(ComboBox));
style.Setters.Add(new EventSetter(ComboBox.SelectionChangedEvent, new SelectionChangedEventHandler(SomeSelectionChanged)));
dataGridComboBoxColumn.EditingElementStyle = style;
To Complete Kevinpo answer, for the code behind you should add some protection because the selectionChanged event is triggered 2 time with a datagridcolumncombobox:
1) first trigger : when you selected a new item
2) Second trigger : when you click on an other datagridcolumn after you selected a new item
The problem is that on the second trigger the ComboBox
value is null because you don't have changed the selected item.
private void SomeSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var comboBox = sender as ComboBox;
if (comboBox.SelectedItem != null)
{
YOUR CODE HERE
}
}
That was my problem, I wish it will help someone else !
The problem of getting SelectionChanged events to fire on DataGridComboBoxColumn cells was one that plagued me recently. I used the following solution:
private void DataGridView_PreparingCellForEdit(object sender, DataGridPreparingCellForEditEventArgs e)
{
if (e.Column.DisplayIndex == 3) //Use this IF statement to specifiy which combobox columns you want to attach the event to.
{
ComboBox? cb = e.EditingElement as ComboBox;
if (cb != null)
{
// As this event fires everytime the user starts editing the cell you need to dettach any previously attached instances of "My_SelectionChanged", otherwise you'll have it firing multiple times.
cb.SelectionChanged -= My_SelectionChanged;
// now re-attach the event handler.
cb.SelectionChanged += My_SelectionChanged;
}
}
}
Then set up your custom SelectionChanged event handler to whatever you need:
private void My_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Your event code here...
}
I created a ListBox with ListBoxItems and add an MouseDown event handler to each of the ListBoxItems. The ListBoxItems are shown, but when I click on a ListBoxItem, the Event doesn't get fired.
How i set the MouseUp:
TrackedProcessList.ItemsSource = null;
TrackedProcessList.ItemsSource = this.tracks;
/*... some other code that doesn't matter ... */
ListBoxItem[] items = new ListBoxItem[TrackedProcessList.Items.Count];
for (int i = 0; i < TrackedProcessList.Items.Count; i++)
{
Object obj = TrackedProcessList.Items.GetItemAt(i);
//TrackedProcessList.UpdateLayout();
ListBoxItem item = (ListBoxItem)(TrackedProcessList.ItemContainerGenerator.ContainerFromIndex(i));
if (item != null)
{
item.MouseUp += new MouseButtonEventHandler(ListBoxItem_MouseUp_PostQuestion);
items[i] = item;
}
}
The Method which should be called (but it isn't):
private void ListBoxItem_MouseUp_PostQuestion(object sender, EventArgs e)
{
MessageBox.Show("ListBoxItem_MouseUp_fired");
}
My XAML:
<ListBox x:Name="TrackedProcessList" Height="145" Width="605" ItemsSource="{Binding}" BorderThickness="1,0" IsSynchronizedWithCurrentItem="True">
<DataTemplate>
<TextBlock MouseDown="ListBoxItem_MouseUp_PostQuestion" Text="{Binding Path=programName}" HorizontalAlignment="Stretch" ></TextBlock>
</DataTemplate>
</ListBox>
Do you have any ideas where the failure could be? There is no error. The Event just seems to be not bound to the ListBoxItem.
It is because ListBoxItem already handles both left and right click which means your event handler will not be triggered according to WPF routed event rules. Your either have to assign PreviewMouseDown event or add event handler for handled events:
lbi.AddHandler(ListBoxItem.MouseDownEvent, new MouseButtonEventHandler(MouseEvent), true);
void OnListBox_Mouse_Down(object sender, MouseButtonEventArgs e)
{
e.Handled
}
void OnListBox_Mouse_Up(object sender, MouseButtonEventArgs e)
{
"Do Something";
}
Use the ContainedControl property and set your events :)
kryptonListBox1.ContainedControl.MouseDown += kryptonListBox1_MouseDown_1;