I would like to have a TabControl with two TabItems and one Listbox on each Item. I want both ListBoxes to show the same content and so I bound both to the same ObservableCollection<T>. At first the items are shown correctly in Listbox1. Also if i switch to ListBox2 the Items show up here as well. If I go back to Listbox1 afterwards all the items are gone and stay in ListBox2. I want both ListBoxes to hold and show the same ListBoxItems constantly. Really would appreciate some help!
My XAML Code:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="350*"/>
<RowDefinition Height="100*"/>
</Grid.RowDefinitions>
<Button Grid.Row="1" Margin="5,5,5,5" Content="Add" Click="Button_Click"/>
<TabControl Grid.Row="0">
<TabItem Header="Test1">
<ListBox ItemsSource="{Binding Components}"/>
</TabItem>
<TabItem Header="Test2">
<ListBox ItemsSource="{Binding Components}"/>
</TabItem>
</TabControl>
</Grid>
CS Code:
private ListBoxItem _oBoxItem;
private Int32 i = 0;
private ObservableCollection<ListBoxItem> components = new ObservableCollection<ListBoxItem>();
public ObservableCollection<ListBoxItem> Components
{
get
{
if (components == null)
components = new ObservableCollection<ListBoxItem>();
return components;
}
}
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
_oBoxItem = new ListBoxItem();
_oBoxItem.Content = "Part " + i.ToString();
Components.Add(_oBoxItem);
i += 1;
}
Don't add any visual elements such as ListBoxItem to the source collection. Add strings instead and you will get the expected results:
public partial class MainWindow : Window
{
private Int32 i = 0;
private ObservableCollection<string> components = new ObservableCollection<string>();
public ObservableCollection<string> Components
{
get
{
if (components == null)
components = new ObservableCollection<string>();
return components;
}
}
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Components.Add("Part " + i.ToString());
i += 1;
}
}
A visual element can only appear once in the visual tree. This basically means that the ListBoxItem that you add to the first ListBox cannot be displayed in the second ListBox and vice versa.
Related
hi I'm try to develop Datalogger, so i create a menu, to Switch de Options i decided to use DataTemplates and different ViewModels.
Menu
XAML:
<Window.Resources>
<DataTemplate x:Name="GraficoVtemplate" DataType="{x:Type viewmodels:GraficoVM}">
<view:GraficoV DataContext="{Binding}" />
</DataTemplate>
<DataTemplate x:Name="ListaVtemplate" DataType="{x:Type viewmodels:ListaVM}">
<view:ListaV DataContext="{Binding }"/>
</DataTemplate>
<ContentControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="4" Grid.RowSpan="5" Content="{Binding}"/>
This is how i change the datacontext;
XAML.CS
private void Novoteste_btn_Click(object sender, RoutedEventArgs e)
{
DataContext = new NovoTesteVM();
}
private void Lista_btn_Click(object sender, RoutedEventArgs e)
{
DataContext = new ListaVM();
}
This is the files that i have, the models are empty and the viewsmodals have some controles.Files
The problem is that when I change the menu, the content of the previous menu is not saved, that is when I select the menu "lista" and fill in a datagrid, and I go to another menu when I select again the menu "lista" the data are lost.I do not know what I need to add, or change so that the data is not lost
Thanks you for the explanation!
Edit 1:
MainWindows.xaml.cs
private void Novoteste_btn_Click(object sender, RoutedEventArgs e)
{
DataContext = NovoTesteVM.NovoTesteViewModel;
}
private void Grafico_btn_Click(object sender, RoutedEventArgs e)
{
DataContext = GraficoVM.Grafico;
}
NovoTesteVM.cs
public class NovoTesteVM
{
private static NovoTesteVM novoTesteViewModel;
public static NovoTesteVM NovoTesteViewModel
{
get
{
novoTesteViewModel = novoTesteViewModel ?? new NovoTesteVM();
return novoTesteViewModel;
}
}
}
Create container properties to keep the wiewmodel for corresponding views. It's loosing data because you are initializing new object on click.
Sample code -
private NovoTesteVM novoTesteViewModel;
public NovoTesteVM NovoTesteViewModel
{
get
{
novoTesteViewModel = novoTesteViewModel ?? new NovoTesteViewModel();
return novoTesteViewModel;
}
}
I'm trying to do some basic UI and binding in UWP to get my head wrapped around it but I'm having trouble accessing a button within a listview item.
I have a Button where on clicking it, it creates a new object which is added to my ObservableCollection which then ends up adding a new item in my ListView
XMAL
<ListView Grid.Row="1" ItemsSource="{x:Bind counts}" x:Name="buttonsView" Margin="5,0" Background="White" Foreground="#FF5059AB">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Counter">
<StackPanel Orientation="Vertical">
<TextBlock Text="{x:Bind CountValue, Mode=TwoWay}" FontWeight="Black"/>
<Button Click="Increment_Click" Content="Increment"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
C#
public class Counter
{
private int count;
public Counter()
{
count = 0;
}
public int CountValue
{
get
{
return count;
}
set
{
count = value;
}
}
}
public sealed partial class MainPage : Page
{
ObservableCollection<Counter> counts = new ObservableCollection<Counter>();
public MainPage()
{
this.InitializeComponent();
}
private void Increment_Click(object sender, RoutedEventArgs e)
{
// ?
}
private void AddCounter_Click(object sender, RoutedEventArgs e)
{
counts.Add(new Counter());
}
}
That works.
But when I click on the button within the StackPanel, the Increment_Click method is called but I'm not sure what to do at that point. I would like to access the Counter object by getting the index of the ListView item and using that to index into the ObservableCollection.
How do I figure out what the index is of the ListView item that was added?
Instead of an event you should use Command and CommandParameter. You would then bind the Command to a command implemented in Counter and CommandParameter to the item (like {Binding}).
However, you can achieve your goal with Click event as well using DataContext:
private void Increment_Click(object sender, RoutedEventArgs e)
{
var button = (Button)sender;
var counter = (Counter)button.DataContext;
//...
}
Basically DataContext is by default inherited from the parent unless you specify otherwise, so in this case DataContext is the current list item.
Below is an mcve (to reproduce the problem it has to be datatemplated unloadable view).
xaml:
<Window Content="{Binding}" ... >
<Window.Resources>
<DataTemplate DataType="{x:Type local:ViewModel}">
<ListView ItemsSource="{Binding Items}"
SelectionChanged="ListView_SelectionChanged"
Unloaded="ListView_Unloaded"
MouseRightButtonDown="ListView_MouseRightButtonDown">
</ListView>
</DataTemplate>
</Window.Resources>
</Window>
cs:
public class ViewModel
{
public ObservableCollection<string> Items { get; set; } = new ObservableCollection<string>(new[] { "1", "2", "3" });
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) => Title += "S";
void ListView_Unloaded(object sender, RoutedEventArgs e) => Title += "U";
void ListView_MouseRightButtonDown(object sender, MouseButtonEventArgs e) => DataContext = null;
}
Start program, select item in the list ("S" will be added to title), right click inside list -> "SU" will be added to title.
Question: why SelectionChanged is called when view (ListView) is unloaded??
Right-clicking without selecting anything will add only "U" to the tittle.
Simply closing software (disregarding selection) will not cause SelectionChanged (tested by setting breakpoint).
I will have some logic in SelectionChanged event and I don't want it to run when view is unloaded, it's unexpected behavior what SelectionChanged event is called in this case at all.
I am working in WPF -- There is button with click event handler in my application. As i click on button it's event handler generates a new row in grid named as grids. In this new Row i want to add another grid programmatically to add Label, Button and TextBox in this grid in row.
As i executed my code it only generates a texboxes! where labels and button shown once! Here code and image is : Please feel free to ask if my query is not clear to you!
int r =0;
private void button2_Click(object sender, RoutedEventArgs e)
{
TextEdit text1; Button button1; Grid grid1;
grids.RowDefinitions.Add(new RowDefinition());
text1 = new TextEdit();
text1.SetValue(Grid.ColumnProperty, 1);
text1.SetValue(Grid.RowProperty, r);
button1 = new Button();
button1.Content = "Left + " + r;
button1.Click += new RoutedEventHandler(button1_Click);
button1.SetValue(Grid.ColumnProperty, 1);
button1.SetValue(Grid.RowProperty, r);
grid1 = new Grid();
grid1.SetValue(Grid.ColumnProperty, 1);
grids.RowDefinitions.Add(new RowDefinition());
grid1.SetValue(Grid.RowProperty, r);
grids.Children.Add(button1);
grids.Children.Add(text1);
r = r + 1;
}
EDIT
int r =0;
private void button2_Click(object sender, RoutedEventArgs e)
{
db obj = new db();
var query = from p in obj.TableA select p ;
foreach(var a in query.ToList())
{
TextEdit text1; Button button1; Grid grid1;
grids.RowDefinitions.Add(new RowDefinition());
text1 = new TextEdit();
text1.SetValue(Grid.ColumnProperty, 1);
text1.SetValue(Grid.RowProperty, r);
button1 = new Button();
button1.Content = a.name;
button1.Click += new RoutedEventHandler(button1_Click);
button1.SetValue(Grid.ColumnProperty, 1);
button1.SetValue(Grid.RowProperty, r);
grid1 = new Grid();
grid1.SetValue(Grid.ColumnProperty, 1);
grids.RowDefinitions.Add(new RowDefinition());
grid1.SetValue(Grid.RowProperty, r);
grids.Children.Add(button1);
grids.Children.Add(text1);
r = r + 1;}
}
Ok. Delete all your code and start all over.
If you're working with WPF, you really need to have The WPF Mentality
As a general rule, you almost never create or manipulate UI elements in procedural code in WPF.
That's what XAML is for.
This the right way to do what you're asking in WPF (in a full working example):
<Window x:Class="MiscSamples.ItemsControlSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
Title="ItemsControlSample" Height="300" Width="300">
<DockPanel>
<Button Content="Add New Row" Command="{Binding AddNewRowCommand}"
DockPanel.Dock="Bottom"/>
<ItemsControl ItemsSource="{Binding Data}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" Background="Gainsboro" BorderThickness="1" Margin="2">
<!-- This is the Inner Grid for each element, which is represented in Brown color in your picture -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width=".2*"/>
<ColumnDefinition Width=".2*"/>
</Grid.ColumnDefinitions>
<Label Content="{Binding Label1Text}"
Margin="2"/>
<Button Content="Button1"
Command="{Binding DataContext.Command1, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}"
Grid.Column="1" Margin="2"/>
<Button Content="Button2"
Command="{Binding DataContext.Command2, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}"
Grid.Column="2" Margin="2"/>
<dxe:TextEdit Text="{Binding Text}"
Grid.Row="1" Grid.ColumnSpan="3"
Margin="2"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Template>
<ControlTemplate TargetType="ItemsControl">
<ScrollViewer CanContentScroll="True">
<ItemsPresenter/>
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DockPanel>
</Window>
Code Behind:
public partial class ItemsControlSample : Window
{
public ItemsControlSample()
{
InitializeComponent();
DataContext = new ItemsControlSampleViewModel();
}
}
ViewModel:
public class ItemsControlSampleViewModel
{
public ObservableCollection<ItemsControlSampleData> Data { get; set; }
public Command AddNewRowCommand { get; set; }
public Command<ItemsControlSampleData> Command1 { get; set; }
public Command<ItemsControlSampleData> Command2 { get; set; }
public ItemsControlSampleViewModel()
{
var sampledata = Enumerable.Range(0, 10)
.Select(x => new ItemsControlSampleData()
{
Label1Text = "Label1 " + x.ToString(),
Text = "Text" + x.ToString()
});
Data = new ObservableCollection<ItemsControlSampleData>(sampledata);
AddNewRowCommand = new Command(AddNewRow);
Command1 = new Command<ItemsControlSampleData>(ExecuteCommand1);
Command2 = new Command<ItemsControlSampleData>(ExecuteCommand2);
}
private void AddNewRow()
{
Data.Add(new ItemsControlSampleData() {Label1Text = "Label 1 - New Row", Text = "New Row Text"});
}
private void ExecuteCommand1(ItemsControlSampleData data)
{
MessageBox.Show("Command1 - " + data.Label1Text);
}
private void ExecuteCommand2(ItemsControlSampleData data)
{
MessageBox.Show("Command2 - " + data.Label1Text);
}
}
Data Item:
public class ItemsControlSampleData
{
public string Label1Text { get; set; }
public string Text { get; set; }
}
Helper classes:
public class Command : ICommand
{
public Action Action { get; set; }
public string DisplayName { get; set; }
public void Execute(object parameter)
{
if (Action != null)
Action();
}
public bool CanExecute(object parameter)
{
return IsEnabled;
}
private bool _isEnabled = true;
public bool IsEnabled
{
get { return _isEnabled; }
set
{
_isEnabled = value;
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
}
}
public event EventHandler CanExecuteChanged;
public Command(Action action)
{
Action = action;
}
}
public class Command<T>: ICommand
{
public Action<T> Action { get; set; }
public void Execute(object parameter)
{
if (Action != null && parameter is T)
Action((T)parameter);
}
public bool CanExecute(object parameter)
{
return IsEnabled;
}
private bool _isEnabled = true;
public bool IsEnabled
{
get { return _isEnabled; }
set
{
_isEnabled = value;
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
}
}
public event EventHandler CanExecuteChanged;
public Command(Action<T> action)
{
Action = action;
}
}
Result:
Notice how I'm not dealing with UI in procedural code, but instead I'm using DataBinding and simple, simple properties. That's how you program in WPF. That's what the WPF mentality is about.
I'm using an ItemsControl and a DataTemplate defined in XAML to let WPF create the UI for each of my data items.
Also notice how my code does nothing except expose the data and define reusable Commands that serve as abstractions to the user actions such as Button clicks. This way you can concentrate in coding your business logic instead of struggling with how to make the UI work.
The buttons inside each item are bound to the Commands using a RelativeSource Binding to navigate upwards in the Visual Tree and find the DataContext of the ItemsControl, where the Commands are actually defined.
When you need to add a new item, you just add a new item to the ObservableCollection that contains your data and WPF automatically creates the new UI elements bound to that.
Though this might seem like "too much code", most of the code I posted here is highly reusable and can be implemented in a Generic ViewModel<T> that is then reusable for any type of data items. Command and Command<T> are also write-once reusable classes that can be found in any MVVM framework such as Prism, MVVM Light or Caliburn.Micro.
This approach is really much preferred in WPF, because it enables a great amount of scalability and independence between the UI and the business logic, and it also enables testability of the ViewModel.
I suggest you read all the materials linked in the post, most importantly Rachel's WPF Mentality and related blog posts. Let me know if you need further help.
WPF Rocks. Just copy and paste my code in a File -> New Project -> WPF Application and see the results for yourself.
It's actually much easier in behind code then in xaml code..
My Xaml code:
<Window x:Class="WpfAddGridWithStackPanel.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid x:Name="Grid_Grid" Margin="0,0,0,32">
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<Grid x:Name="Grid_Grid" Margin="0,0,0,32"/>
</ScrollViewer>
<Button x:Name="btn_Add" Height="32" DockPanel.Dock="Bottom" VerticalAlignment="Bottom" Content="Add New Row" Click="btn_Add_Click" Width="150" HorizontalAlignment="Left" UseLayoutRounding="True" />
<Button x:Name="btn_Remove" Height="32" DockPanel.Dock="Bottom" VerticalAlignment="Bottom" Content="Remove last Row" Click="btn_Remove_Click" Width="150" HorizontalAlignment="Right" />
</Grid>
</Window>
And Code behind:
public partial class MainWindow : Window
{
int num = 0;
public MainWindow()
{
InitializeComponent();
}
void btn1_Click(object sender, RoutedEventArgs e)
{
throw new NotImplementedException();
}
void btn2_Click(object sender, RoutedEventArgs e)
{
throw new NotImplementedException();
}
private void btn_Remove_Click(object sender, RoutedEventArgs e)
{
try
{
Grid_Grid.RowDefinitions.RemoveAt(Grid_Grid.RowDefinitions.Count - 1);
Grid_Grid.Children.RemoveAt(Grid_Grid.Children.Count - 1);
num--;
}
catch { }
}
private void btn_Add_Click(object sender, RoutedEventArgs e)
{
StackPanel stack = new StackPanel();
DockPanel dock = new DockPanel();
Label lbl = new Label();
Button btn1 = new Button();
Button btn2 = new Button();
TextBox txt1 = new TextBox();
stack.Children.Add(dock);
stack.Children.Add(txt1);
dock.Children.Add(lbl);
dock.Children.Add(btn2);
dock.Children.Add(btn1);
#region StackPanel Properties
stack.Background = Brushes.LightGray;
#endregion
#region DockPanel Content Properties
lbl.Content = "Label " + (num + 1).ToString();
lbl.Height = 32;
lbl.Width = 100;
lbl.FontSize = 12;
lbl.SetValue(DockPanel.DockProperty, Dock.Left);
lbl.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
btn1.Content = "Butten 1";
btn1.Height = 32;
btn1.Width = 100;
btn1.FontSize = 12;
btn1.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
btn1.SetValue(DockPanel.DockProperty, Dock.Right);
btn1.Click += new RoutedEventHandler(btn1_Click);
btn2.Content = "Butten 2";
btn2.Height = 32;
btn2.Width = 100;
btn2.FontSize = 12;
btn2.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
btn2.SetValue(DockPanel.DockProperty, Dock.Right);
btn2.Click += new RoutedEventHandler(btn2_Click);
#endregion
#region TextBox Properties
txt1.Text = "Text " + (num + 1).ToString();
txt1.Height = 32;
txt1.Width = double.NaN;
txt1.FontSize = 12;
txt1.Padding = new Thickness(0, 7, 0, 7);
#endregion
Grid_Grid.RowDefinitions.Add(new RowDefinition());
Grid_Grid.RowDefinitions[num].Height = new GridLength(66, GridUnitType.Pixel);
Grid_Grid.Children.Add(stack);
stack.SetValue(Grid.RowProperty, num);
num++;
}
}
I currently have an Entity that has a collection property on it. I want to know if why would the SelectionChanged only fire once and it won't trigger the SelectionChanged again once I try to select the item that was previously selected.
MainWindowViewModel
public MainWindowViewModel()
{
var a = new List<Test>();
a.Add(new Test() { Name = "Leo", Test1 = new List<Test1> { new Test1() { Content = "aaa"} } });
a.Add(new Test() { Name = "2", Test1 = new List<Test1> { new Test1() { Content = "bbb"} } });
a.Add(new Test() { Name = "Le33o", Test1 = new List<Test1> { new Test1() { Content = "ccc"} } });
A = a;
}
private List<Test> _a;
public List<Test> A
{
get { return _a; }
set { _a = value; OnPropertyChanged("A");}
}
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
public event PropertyChangedEventHandler PropertyChanged;
My Mainwindow
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
private void Test(object sender, SelectionChangedEventArgs e)
{
}
My listbox structure
public class Test
{
public List<Test1> Test1 { get; set; }
public string Name
{
get;set;
}
}
public class Test1
{
public string Content { get; set; }
}
I select the first object, the event fires, I select the second object, the event fires, I select the first object, the event doesn't fire, I select third object, the event fires. It seems like it only triggers and calls the event once.
My XAML Code:
<ItemsControl x:Name="Lists" ItemsSource="{Binding A}" Grid.Row="1">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}" FontWeight="Bold"
Style="{StaticResource DefaultTextBlockStyle}" />
<ListBox SelectionChanged="Test" ItemsSource="{Binding Test1}"
Margin="5,0,0,0" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Content}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The test method is just an empty method I just want to hit the breakpoint every time I change.
private void Test(object sender, SelectionChangedEventArgs e)
{
}
Update 1: I tried to reproduce this in a simple WPF app, it seems that the ListBoxItem is getting IsEnabled to false but I snooped it and all the controls are enabled. It just getting a grey background that looks like disabled. Will try to investigate further.
Update 2: It seems that the ListBoxItem IsSelected property is not being unset when you change an item.
To answer your question ...
I want to know if why would the SelectionChanged only fire once and it won't trigger the SelectionChanged again once I try to select the
item that was previously selected.
... in a learning by doing way
open a new WPF Project add 2 Listboxes create ONE SelectionChanged event for both and add some items to each Listbox
let's mention it look's now like this
<ListBox Height="100" Name="listBox1" Width="120" SelectionChanged="listBox_SelectionChanged"/>
<ListBox Height="100" Name="listBox2" Width="120" SelectionChanged="listBox_SelectionChanged"/>
.
var list = new List<string>();
list.Add("Element1");
list.Add("Element2");
list.Add("Element3");
list.Add("Element4");
listBox1.ItemsSource = list;
listBox2.ItemsSource = list;
If you now select Element1 in listBox1 your listBox_SelectionChanged get triggert after that select Element2 in your listBox2 so your listBox_SelectionChanged get's triggert again.
If you take a closer look at your listBox1 you will see that the Background behind your Element1 is gray which means it is selected, but with out focuse. If you select now the Element1 in your listBox1 again the listBox_SelectionChanged doesn't get triggert because the selection does't change only the Focuse does.
That's the exact same "problem" is in your code because your DataTemplate does the same think we did as we added our 2 Listboxes just automatically
as simple and dirt workaround you could use the following code
private object seletedItem;
private ListBox ItemsHost;
private void Test(object sender, SelectionChangedEventArgs e)
{
var buff = sender as ListBox;
if (seletedItem != null)
if (ItemsHost != buff)
ItemsHost.SelectedItem = null;
ItemsHost = buff;
if (e.AddedItems.Count > 0)
seletedItem = e.AddedItems[0];
}
The simple solution I found out is to make selectedItem as null in the event handler.
private void tempList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Card selectedOffer = (TempList.SelectedItem as Card);
if (selectedOffer != null)
{
MessageBox.Show(selectedOffer._id);
}
ListBoxNeeded.SelectedItem = null;
}
Selecting the same item is not a SelectionChanged event. The selection did not change.
The problem statement is not clear.
Break it down. This works for me. If I select any item a second time, 3rd, 4th time the event fires.
OP asserted it does not work if it is a List in a List. Still works for me.
public MainWindow()
{
this.DataContext = this;
InitializeComponent();
}
public List<ListList> ListList1
{
get { return new List<ListList>{new ListList("name1", new List<string> { "one", "two", "three" })}; }
}
private void Test(object sender, SelectionChangedEventArgs e)
{
ListBox lb = (ListBox)sender;
System.Diagnostics.Debug.WriteLine(lb.SelectedItem.ToString());
}
public class ListList
{
public string Name { get; set; }
public List<string> Values { get; set; }
public ListList(string name, List<string> values) { Name = name; Values = values; }
}
<ListBox ItemsSource="{Binding Path=ListList1}">
<ListBox.ItemTemplate>
<DataTemplate>
<ListBox SelectionChanged="Test" ItemsSource="{Binding Path=Values}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>