Selecting a Textbox Item in a Listbox Does Not Change the Selected Item of the Listbox

Listbox selection become textbox selection

selectedItems is a String and strings don't have any properties such as Text

TextBox1.Value = selectedItems

would be what you need

Binding a TextBox to a ListBox SelectedItem

As described in the comments, associating a BindingList (or a DataTable) with a BindingSource can have some interesting benefits.

All bound controls are updated automatically when one of the elements of the BindingList is modified or a new element is added to the list.

You can use the MovePrevious(), MoveNext(), MoveFirst(), MoveLast() methods to navigate the elements in the BindingList (other useful methods and events are available, see the Docs about the BindingSource functionality).

Here, a BindingList<T> (where T is the Member class shown below) is set as the DataSource of a BindingSource. Both are Fields of a Form class, this can be modified as needed.

The BindingSource is then used as the DataSource of a ListBox.

The Text property of two TextBox controls is then bound, using the BindingSource, to one of the properties of the Member class. This way, the Text property is set to the current Item of the BindingList. All controls are synchronized:

txtMemberName.DataBindings.Add(new Binding("Text", membersSource, 
"FirstName", false, DataSourceUpdateMode.OnPropertyChanged));
txtMemberLastName.DataBindings.Add(new Binding("Text", membersSource,
"LastName", false, DataSourceUpdateMode.OnPropertyChanged));

This is how it works, in practice:

BindingSource and BindingList

Note that the current Item of the ListBox is updated in real time when the Text of a TextBox is modified.

BindingList<Member> members = null;
BindingSource membersSource = null;

public partial class frmMembers : Form
{
public frmMembers() {
InitializeComponent();
InitializeDataBinding();
}

private void InitializeDataBinding()
{
members = new BindingList<Member>();
membersSource = new BindingSource(members, null);

lstBoxMembers.DataSource = membersSource;
txtMemberName.DataBindings.Add(new Binding("Text", membersSource,
"FirstName", false, DataSourceUpdateMode.OnPropertyChanged));
txtMemberLastName.DataBindings.Add(new Binding("Text", membersSource,
"LastName", false, DataSourceUpdateMode.OnPropertyChanged));
}

private void btnAddMember_Click(object sender, EventArgs e)
{
var frmNew = new frmNewMember();
if (frmNew.ShowDialog() == DialogResult.OK && frmNew.newMember != null) {
members.Add(frmNew.newMember);
}
}

private void btnMovePrevious_Click(object sender, EventArgs e)
{
if (membersSource.Position > 0) {
membersSource.MovePrevious();
}
else {
membersSource.MoveLast();
}
}

private void btnMoveNext_Click(object sender, EventArgs e)
{
if (membersSource.Position == membersSource.List.Count - 1) {
membersSource.MoveFirst();
}
else {
membersSource.MoveNext();
}
}
}

Sample New Member Form:

public partial class frmNewMember : Form
{
public Member newMember;

private void btnSave_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(txtMemberName.Text) ||
string.IsNullOrEmpty(txtMemberLastName.Text)) return;
newMember = new Member(txtMemberName.Text, txtMemberLastName.Text);
}
}

Sample Member class:

[Serializable()]
public class Member
{
public Member() { }
public Member(string firstName, string lastName)
{
this.FirstName = firstName;
this.LastName = lastName;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public override string ToString() => $"{this.FirstName} {this.LastName}";
}

How to change selected item of listbox when clicking on the Button / textbox in ItemTemplate?

You could handle the PreviewMouseLeftButtonDown event for the Border element in the template and explicitly select the corresponding item:

private void Border_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Border border = sender as Border;
lvv.SelectedItem = border.DataContext;
}

<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="Border" Padding="2" SnapsToDevicePixels="true"
PreviewMouseLeftButtonDown="Border_PreviewMouseLeftButtonDown">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border" Property="BorderBrush" Value="Blue"/>
<Setter TargetName="Border" Property="BorderThickness" Value="1"/>
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Foreground" Value="Black" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>

Update a TextBox Text from a ListBox Item when other TextBox TextChanged its triggered inside the same listbox item WPF

You can use ItemTemplate

This is my code
MainWindow:

<Window x:Class="WpfApplication.Wpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication.Wpf"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<ListBox ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="5">
<TextBox x:Name="source" FontSize="16" Text="{Binding Path=ItemTitle}" HorizontalAlignment="Center" />
<TextBlock FontSize="16" Text="{Binding ElementName=source, Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>

Model of Item:

public class ItemModel
{
public string ItemTitle { get; set; }
}

And main window Viewmodel:

public class MainWindowViewModel
{
public ObservableCollection<ItemModel> Items { get; set; }

public MainWindowViewModel()
{
Items = new ObservableCollection<ItemModel>
{
new ItemModel { ItemTitle = "exemple title 1" },
new ItemModel { ItemTitle = "exemple title 2" },
};
}
}

Result:
Sample Image

upd:

And project:

Sample Image

UPD 2:

else you can use UserControl:

just move the template to a custom control and set UserControl as the template for the ListBox

UserControl:

<UserControl x:Class="WpfApplication.Wpf.ItemBoxTemplate"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApplication.Wpf"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" Background="White">
<Grid>
<StackPanel Margin="5">
<TextBox x:Name="source" FontSize="16" Text="{Binding Path=ItemTitle}" HorizontalAlignment="Center" />
<TextBlock FontSize="16" Text="{Binding ElementName=source, Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" />
</StackPanel>
</Grid>
</UserControl>

And MainWindow:

<Window x:Class="WpfApplication.Wpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication.Wpf"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<ListBox ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<local:ItemBoxTemplate />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>

The rest of the code remains unchanged.

ListBox Not Selecting the Selected Item

I've rewritten your code a bit. The trick is to use a MouseCapture to avoid having multiple event handling (with your original code, the listBox was getting up to three selection for a single click due to the layout changeing while mouse button was pressed)

Here is the code :

MainWindow.xaml

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="TextEditor.MainWindow"
Title="MainWindow" Height="350" Width="525">

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Text="{Binding Path=BoundText}" TextWrapping="Wrap" />
<ListBox Grid.Row="1"
ItemsSource="{Binding Path=BoundList}"
SelectedItem="{Binding Path=BoundListSelected, Mode=TwoWay}"/>
</Grid>

</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;

namespace TextEditor
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public string BoundText
{
get { return (string)GetValue(BoundTextProperty); }
set { SetValue(BoundTextProperty, value); }
}

// Using a DependencyProperty as the backing store for BoundText. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BoundTextProperty =
DependencyProperty.Register("BoundText", typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty));

public string BoundListSelected
{
get { return (string)GetValue(BoundListSelectedProperty); }
set { SetValue(BoundListSelectedProperty, value); }
}

// Using a DependencyProperty as the backing store for BoundListSelected. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BoundListSelectedProperty =
DependencyProperty.Register("BoundListSelected", typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty, OnBoundListSelectedChanged));

private static void OnBoundListSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var mainWindow = d as MainWindow;
var value = e.NewValue as string;

Mouse.Capture(mainWindow);

if (Int32.Parse(value) % 2 == 0)
{
mainWindow.BoundText = value.ToString() + " something very long something very long something very long something very long something very long something very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very long";
}
else
{
mainWindow.BoundText = value.ToString() + " something short ";
}

mainWindow.ReleaseMouseCapture();
}

public MainWindow()
{
for (int i = 0; i < 1000; i++)
{
boundList.Add(i.ToString());
}

InitializeComponent();
DataContext = this;
}

public List<string> BoundList { get { return boundList; } }
private List<string> boundList = new List<string>();
}
}

Edit : I actually changed the way MainWindow was coded (it's not necessary to implement INotifyPropertyChanged on a DependencyObject, so i just removed it and set two dependency properties) but you could try solving your issue with your ogirinal code by simply capturing the mouse before setting BoundText, and then releasing it.

Selecting mutliple items in a WPF ListBox only selects the first selected item

Thanks to @Andy for the solution.

The problem was that the ListBox Option IsSynchronizedWithCurrentItem="True" caused the ListBox to limit itself to a "Single Selection Mode" doesn't reflect in the SelectionMode itself though.

Changing the ListBox from:

<ListBox IsSynchronizedWithCurrentItem="True" SelectionMode="Multiple" />

do this by removing the IsSynchronizedWithCurrentItem Option:

<ListBox SelectionMode="Multiple" />

should fix this problem!



Related Topics



Leave a reply



Submit