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:
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:
upd:
And project:
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
Put Wpf Control into a Windows Forms Form
Serialize Property, But Do Not Deserialize Property in JSON.Net
How to Select Xml Nodes with Xml Namespaces from an Xmldocument
Force JSON.Net to Include Milliseconds When Serializing Datetime (Even If Ms Component Is Zero)
How to Share Data Between Forms
Datatrigger Does Not Change Text Property
Add Shape Information to a Listview When Its Created
Metadata Were Not Loaded Using Metadatatype
When Should I Use Gc.Suppressfinalize()
Additional Text Encountered After Finished Reading JSON Content:
Transitive References in .Net Core 1.1
Why Datetime.Addhours Doesn't Seem to Work
How to Read Regex Captures in C#
How to Get Around the "'" Problem in SQLite and C#