how to split listbox items to some textbox
-
Wednesday, August 29, 2012 3:01 PM
Hi All.
My form has three TextBox. When user enter data to those TextBox and press Add button the data will display in ListBox like one item. For that I use code
TextList.Items.Add(CustomerNoTextBox.Text + VisitNoTextBox.Text + "-" + NoTextBox.Text)
For instance, user enter: TextBox1 - 123456 TextBox2- 7 and TextBox3 - 89.
By click Add button the ListBox will display 1234567-89.
Now I would like in case if will need to modify entered date user will select ListBoxItem and data of that item will display in each TextBox like was entered. If that possible how it to do? I will appreaciat for sample.
Thanks.
- Edited by zleug Wednesday, August 29, 2012 3:10 PM
All Replies
-
Wednesday, August 29, 2012 4:09 PM
Hi eugzl,
CustomerNoTextBox(6), VisitNoTextBox(1), NoTextBox(2) these fields have fixed size or user can enter any length of data.
Regards
Ashish
-
Wednesday, August 29, 2012 4:38 PM
Hi Ashish. Thanks for replay.
All TextBox have fixed legth of data.
Thanks.
- Edited by zleug Wednesday, August 29, 2012 4:39 PM
-
Wednesday, August 29, 2012 4:41 PM
Hello Eugzl.
I got to playing with your described scenario and came up with the following. My thinking was that if textBox1 and textBox2 did not have set lengths then you would need to keep track of each. So I created a ListBoxItem with 3 Properties to keep track.
Here's the sample...
using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace CombiningText { public partial class MainWindow : Window { public MainWindow() { this.InitializeComponent(); } private void Button_Click(object sender, System.Windows.RoutedEventArgs e) { if (btn.Content.ToString() == "Add") addNew(); else { foreach(myListBoxItem lb in myListBox.Items) { if (lb.InEdit) edit(lb); } } } private void editSelected(object sender, MouseButtonEventArgs e) { btn.Content = "Edit"; myListBoxItem lbi = sender as myListBoxItem; lbi.InEdit = true; tb1.Text = lbi.String1; tb2.Text = lbi.String2; tb3.Text = lbi.String3; } private void edit(myListBoxItem lbi) { lbi.InEdit = false; lbi.String1 = tb1.Text; lbi.String2 = tb2.Text; lbi.String3 = tb3.Text; lbi.setContent(); tb1.Text = tb2.Text = tb3.Text = ""; btn.Content = "Add"; } private void addNew() { myListBoxItem lbi = new myListBoxItem(); lbi.String1 = tb1.Text; lbi.String2 = tb2.Text; lbi.String3 = tb3.Text; lbi.InEdit = false; lbi.MouseDoubleClick += editSelected; lbi.setContent(); myListBox.Items.Add(lbi); tb1.Text = tb2.Text = tb3.Text = ""; } } public class myListBoxItem : ListBoxItem { [Category("Item Settings")] public string String1 { get { return (string)GetValue(String1Property); } set { SetValue(String1Property, value); }} public static readonly DependencyProperty String1Property = DependencyProperty.Register("String1", typeof(string), typeof(myListBoxItem), null); [Category("Item Settings")] public string String2 { get { return (string)GetValue(String2Property); } set { SetValue(String2Property, value); }} public static readonly DependencyProperty String2Property = DependencyProperty.Register("String2", typeof(string), typeof(myListBoxItem), null); [Category("Item Settings")] public string String3 { get { return (string)GetValue(String3Property); } set { SetValue(String3Property, value); }} public static readonly DependencyProperty String3Property = DependencyProperty.Register("String3", typeof(string), typeof(myListBoxItem), null); [Category("Item Settings")] public bool InEdit { get { return (bool)GetValue(InEditProperty); } set { SetValue(InEditProperty, value); }} public static readonly DependencyProperty InEditProperty = DependencyProperty.Register("InEdit", typeof(bool), typeof(myListBoxItem), null); public void setContent() { string content = String1 + String2 + "-" + String3; this.Content = content; } } }And the xaml...
<Window 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" x:Class="CombiningText.MainWindow" x:Name="Window" Title="MainWindow" Width="640" Height="480"> <Grid x:Name="LayoutRoot"> <StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Margin="8,8,0,0"> <TextBox x:Name="tb1" TextWrapping="Wrap" Text="TextBox" Margin="5" SelectionOpacity="5" Width="100"/> <TextBox x:Name="tb2" TextWrapping="Wrap" Text="TextBox" Margin="5" SelectionOpacity="5" Width="100"/> <TextBox x:Name="tb3" TextWrapping="Wrap" Text="TextBox" Margin="5" SelectionOpacity="5" Width="100"/> </StackPanel> <Button x:Name="btn" Content="Add" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Margin="8,118,0,0" Click="Button_Click"/> <ListBox x:Name="myListBox" Margin="200,8,0,0" Height="200" VerticalAlignment="Top" HorizontalAlignment="Left" Width="150"/> </Grid> </Window>
Double-Clicking an item added to the listBox will allow it to be edited.
Hope that gives you some ideas.
~Christine
Woops. Forgive the intrusion. I had this open and didn't see that agrawal was already addressing your question.
- Edited by Christine L. _ Wednesday, August 29, 2012 4:44 PM
- Proposed As Answer by XAML guyMicrosoft Community Contributor, Moderator Wednesday, August 29, 2012 8:05 PM
- Unproposed As Answer by zleug Thursday, August 30, 2012 11:44 PM
-
Wednesday, August 29, 2012 6:42 PM
Hi Christine. Thanks for replay.
Your code is greate. In my code I have Delete button for in case user enter wrong or extra data. The code of Delete button:
Private Sub DelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) TextList.Items.RemoveAt(TextList.Items.IndexOf(TextList.SelectedItem)) End SubBut if ListBoxItem is not selected I got error message: "removeIndex is less than zero or greater than or equal to Count. Parameter name: index."
How modify your code to add Delete button and avoid such problem?
Thanks.
-
Wednesday, August 29, 2012 7:27 PM
Howdy Eugzl.
My first thought was "why not do it with a right-click?" but it's not my place to pretend to know your thinking and how you have your project set up.
So if you have a delete button, what if you had it hidden/collapsed until it could be used. So you double click and can edit or delete the item and use the foreach loop to find and remove it if deleting.
Something like this. (Note because I am right stubborn when I get something in my head, I included the right-click to delete method as well. :) )
using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace CombiningText { public partial class MainWindow : Window { public MainWindow() { this.InitializeComponent(); } private void Button_Click(object sender, System.Windows.RoutedEventArgs e) { if (btn.Content.ToString() == "Add") addNew(); else { foreach(myListBoxItem lb in myListBox.Items) { if (lb.InEdit) edit(lb); } } } private void editSelected(object sender, MouseButtonEventArgs e) { btn.Content = "Edit"; deleteBtn.Visibility = Visibility.Visible; myListBoxItem lbi = sender as myListBoxItem; lbi.InEdit = true; tb1.Text = lbi.String1; tb2.Text = lbi.String2; tb3.Text = lbi.String3; } private void edit(myListBoxItem lbi) { lbi.InEdit = false; lbi.String1 = tb1.Text; lbi.String2 = tb2.Text; lbi.String3 = tb3.Text; lbi.setContent(); tb1.Text = tb2.Text = tb3.Text = ""; btn.Content = "Add"; } private void addNew() { myListBoxItem lbi = new myListBoxItem(); lbi.String1 = tb1.Text; lbi.String2 = tb2.Text; lbi.String3 = tb3.Text; lbi.InEdit = false; lbi.MouseDoubleClick += editSelected; //Right-Click Delete lbi.PreviewMouseRightButtonDown += deleteByRightClick; lbi.setContent(); myListBox.Items.Add(lbi); tb1.Text = tb2.Text = tb3.Text = ""; } private void DeleteItem(object sender, System.Windows.RoutedEventArgs e) { myListBoxItem lbi = new myListBoxItem(); foreach(myListBoxItem lb in myListBox.Items) { if (lb.InEdit) { lbi = lb; } } if (lbi != null) { myListBox.Items.Remove(lbi); tb1.Text = tb2.Text = tb3.Text = ""; btn.Content = "Add"; deleteBtn.Visibility = Visibility.Collapsed; } } private void deleteByRightClick(object sender, MouseButtonEventArgs e) { myListBoxItem lbi = sender as myListBoxItem; var result = MessageBox.Show("Delete Selected Item?", "Delete Item", MessageBoxButton.YesNo); if (result == MessageBoxResult.Yes) { myListBox.Items.Remove(lbi); } } }And the simple deleteBtn xaml...
<Button x:Name="deleteBtn" Content="Delete" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Margin="8,143.96,0,0" Click="DeleteItem" Visibility="Collapsed"/>
~Chritine
- Edited by Christine L. _ Wednesday, August 29, 2012 7:31 PM
-
Wednesday, August 29, 2012 9:18 PMModerator
Use the Tag property to hold the values seperated by pipe characters. I have three textboxes (tbOne, tbTwo, tbThree) a button and a listbox (lbLoad). On the button press I get the values and load the listbox with an item. If the user double clicks I extract the Tag information and load the textboxes. Since you have delete you will need to remove the listbox item for editing. Here is the code:
private List<TextBox> _tbs; public List<TextBox> TextBoxes { get { if (_tbs == null) _tbs = new List<TextBox> {tbOne, tbTwo, tbThree}; return _tbs; } } private void btnAdd_Click( object sender, RoutedEventArgs e ) { var strings = TextBoxes.Select( tb => tb.Text ); lbLoad.Items.Add(new ListBoxItem() { Content = string.Join( string.Empty, strings.ToArray() ), Tag = string.Join( "|", strings.ToArray() ) } ); // Clear the textboxes TextBoxes.ToList() .ForEach(tb => tb.Text = string.Empty); } private void lbLoad_MouseDoubleClick( object sender, MouseButtonEventArgs e ) { var item = lbLoad.SelectedItem as ListBoxItem; if (item != null) { if (item.Tag != null) { string data = (string)item.Tag; if (string.IsNullOrEmpty(data) == false) { var splitData = data.Split('|'); TextBoxes.Select((tb, index) => new {tb, index}) .ToList() .ForEach(tbItem => tbItem.tb.Text = splitData[tbItem.index]); } } } }William Wegerson (www.OmegaCoder.Com)
-
Thursday, August 30, 2012 8:47 PM
Hi All. Thanks for all replays.
I modified ADD procedure to fill ListBox and save data to DataSet CustomerEnterTableAdapter that is point to database SQL Server at the same time. The same I would like to do with EDIT procedure. If need to modify data I will modify data in TextBox and then display modified data in LIstBox and save it to the table by click Edit button.
Public Sub New() ' This call is required by the Windows Form Designer. InitializeComponent() Me.cvCustomerEntry = CollectionViewSource.GetDefaultView(Me.CustomerDataSet.CustomerEntry) Me.DataContext = Me.cvCustomerEntry End Sub Private Sub addNew() Dim Errors As Boolean = False Dim lbi As New myListBoxItem() If Validation.GetHasError(Me.MedRecNoTextBox) Then Me.MedRecNoTextBox.Focus() Errors = True Beep() End If If Validation.GetHasError(Me.VisitNoTextBox) Then Me.VisitNoTextBox.Focus() Errors = True Beep() End If If Validation.GetHasError(Me.NoTextBox) Then Me.NoTextBox.Focus() Errors = True Beep() End If If Errors = True Then MsgBox("Please, fill in all reruired fields") Else lbi.String1 = CustomerNoTextBox.Text lbi.String2 = VisitNoTextBox.Text lbi.String3 = NoTextBox.Text lbi.InEdit = False AddHandler lbi.MouseDoubleClick, AddressOf editSelected lbi.setContent() myListBox.Items.Add(lbi) Me.CustomerEntryTableAdapter.Update(Me.CustomerDataSet.CustomerEntry) End If CustomerNoTextBox.Text = InlineAssignHelper(VisitNoTextBox.Text, InlineAssignHelper(NoTextBox.Text, "")) CustomerNoTextBox.Focus() End SubWhen I open form fill 3 TextBox and click Add button everything works fine. But when I try to add data to ListBox againe I got error message: Update requires a valid UpdateCommand when passed DataRow collection with modified rows.
My goal to add data to LIstBox so many time as need. I validate TextBox for numeric and length entered data. How to fix that problem?Thanks.
- Edited by zleug Thursday, August 30, 2012 8:57 PM
-
Friday, August 31, 2012 5:41 AMModerator
Hi eugzl,
I think your WPF relative issue has been resolved, because " myListBox.Items.Add(lbi)" will work well, and the error message "Update requires a valid UpdateCommand when passed DataRow collection with modified rows." is more relative to Ado.net forum as I suggested before:
On the other hand, WPF and Winform are two different technology, I do not suggest you use WPF ListBox as winform's:
lbi.String1 = CustomerNoTextBox.Text lbi.String2 = VisitNoTextBox.Text lbi.String3 = NoTextBox.Text lbi.InEdit = False AddHandler lbi.MouseDoubleClick, AddressOf editSelected lbi.setContent() myListBox.Items.Add(lbi)I suggest you learn more about DataTemplate of ListBox:
http://msdn.microsoft.com/en-us/library/system.windows.datatemplate.aspx
Best regards,
Sheldon _Xiao[MSFT]
MSDN Community Support | Feedback to us
Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
-
Friday, August 31, 2012 4:48 PM
Hi All.
I modified New procedure like
Public Sub New() ' This call is required by the Windows Form Designer. InitializeComponent() Me.cvCustomeEntry = CollectionViewSource.GetDefaultView(Me.CustomerDataSet.CustomerEntry) myListBox.DataContext = Me.cvCustomeEntry End SubPreviously I had Me.DataContext = Me.cvCustomeEntry. Now I can add data to ListBox as many time as need. But when I click Add button the CustomerEntry table receive only one empty row. How fix that problem?
Thanks.
- Edited by zleug Friday, August 31, 2012 4:49 PM
-
Saturday, September 01, 2012 7:55 PM
I think you are missing Sheldon’s point, with WPF you are better off leveraging Data Binding. By binding Presentation of the data to data source all you have to do in the code behind is manipulate the data not the UI. Any time you add, remove Items to your data you add/remove it from the data source not the UI elements. Because the UI is bound to the data it will reflect the changes automatically. On the flip side if the properties of your items have changed via the User/UI the data source is automatically updated.
Below is an example you can see there is very little code behind to try it create a new WPF project and paste the below XAML over window1’s XAML and Code over window1’s code
XAML:
<Window x:Class="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" > <Window.Resources> <Style x:Key="styEdit" TargetType="TextBox"> <Setter Property="IsEnabled" Value="{Binding ElementName=butEdit, Path=IsChecked}"/> </Style> <BooleanToVisibilityConverter x:Key="VisConv" /> </Window.Resources> <Grid Name="grdLayout" ButtonBase.Click="Button_Click"> <Grid.ColumnDefinitions> <ColumnDefinition Width="120" /> <ColumnDefinition Width="1*" /> </Grid.ColumnDefinitions> <ListBox Name="lstVisits" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock FontSize="14"> <Run Text="{Binding CustomerNo}"/> <Run Text="-"/> <Run FontSize="12" Text="{Binding Path=VisitNo}"/> <Run Text="-"/> <Run FontSize="10" Text="{Binding Path=No}"/> </TextBlock> <Ellipse Fill="#FF40D840" Stroke="Black" StrokeThickness="0.5" Margin="5,0" Width="7" Height="7" Visibility="{Binding Path=FrequentVisitor, Converter={StaticResource ResourceKey=VisConv}}" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <Button Name="butZero" Content="Clear All" HorizontalAlignment="Right" VerticalAlignment="Top" Grid.Column="1" Margin="10"/> <StackPanel Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <TextBox Name="txtCustomerNo" Text="{Binding Path=CurrentItem.CustomerNo}" Style="{StaticResource styEdit}"/> <TextBlock Text="-" Margin="3,0"/> <TextBox Text="{Binding CurrentItem.VisitNo}" Style="{StaticResource styEdit}"/> <TextBlock Text="-" Margin="3,0"/> <TextBox Text="{Binding CurrentItem.No}" Style="{StaticResource styEdit}"/> </StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <Button Name="butAdd" Content="Add"/> <Button Name="butDelete" Content="Delete"/> <ToggleButton Name="butEdit" Content="Edit"/> </StackPanel> </StackPanel> </Grid> </Window>VB Code:
Imports System.Collections.ObjectModel Imports System.ComponentModel Class MainWindow Private _CustomerVisits As ObservableCollection(Of CustomerVisit) Public ReadOnly Property CustomerVisits() As ObservableCollection(Of CustomerVisit) Get If _CustomerVisits Is Nothing Then _CustomerVisits = New ObservableCollection(Of CustomerVisit) AddHandler _CustomerVisits.CollectionChanged, AddressOf CustomerVisit_CollectionChanged End If Return _CustomerVisits End Get End Property Private Sub CustomerVisit_PropertyChanged(sender As Object, _ e As ComponentModel.PropertyChangedEventArgs) 'Code to update database with edits here End Sub Private Sub CustomerVisit_CollectionChanged(sender As Object, _ e As Specialized.NotifyCollectionChangedEventArgs) 'Code to add and delete from database here End Sub Private Sub Button_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) If TypeOf e.OriginalSource Is Button Then Dim ClickedButton As Button = CType(e.OriginalSource, Button) Dim custVisit As CustomerVisit Select Case ClickedButton.Name Case butAdd.Name custVisit = New CustomerVisit 'add items to bound collection ' not from the listbox CustomerVisits.Add(custVisit) lstVisits.SelectedItem = custVisit butEdit.IsChecked = True txtCustomerNo.SelectAll() txtCustomerNo.Focus() Case butDelete.Name 'remove items from bound collection ' not from the listbox. CustomerVisits.Remove(lstVisits.SelectedItem) Case butZero.Name 'clears all values For Each custVisit In CustomerVisits With custVisit .CustomerNo = 0 .VisitNo = 0 .No = 0 End With Next End Select End If End Sub Private Sub lstVisits_SelectionChanged(sender As Object, _ e As System.Windows.Controls.SelectionChangedEventArgs) _ Handles lstVisits.SelectionChanged butEdit.IsChecked = False End Sub 'below code fills the CustomerVisits list with random data Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded grdLayout.DataContext = CustomerVisits LoadCustomerVisits() End Sub Private Sub LoadCustomerVisits() Dim newVisit As CustomerVisit Dim mRand As New Random For i As Integer = 1 To 10 newVisit = New CustomerVisit With newVisit .CustomerNo = mRand.Next(1000, 9999) .VisitNo = mRand.Next(100, 999) .No = mRand.Next(1, 10) End With AddHandler newVisit.PropertyChanged, AddressOf CustomerVisit_PropertyChanged CustomerVisits.Add(newVisit) Next End Sub End Class 'Models the Customer Visit Public Class CustomerVisit 'must implement for databinding Implements INotifyPropertyChanged Public Event PropertyChanged(ByVal sender As Object, _ ByVal e As System.ComponentModel.PropertyChangedEventArgs) _ Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged Protected Overridable Sub OnPropertyChanged(ByVal ChangedProperty As String) RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(ChangedProperty)) End Sub Private _CustomerNo As Integer Public Property CustomerNo() As Integer Get Return _CustomerNo End Get Set(ByVal value As Integer) _CustomerNo = value OnPropertyChanged("CustomerNo") End Set End Property Private _VisitNo As Integer Public Property VisitNo() As Integer Get Return _VisitNo End Get Set(ByVal value As Integer) _VisitNo = value OnPropertyChanged("VisitNo") End Set End Property Private _No As Integer Public Property No() As Integer Get Return _No End Get Set(ByVal value As Integer) _No = value OnPropertyChanged("No") OnPropertyChanged("FrequentVisitor") End Set End Property Public ReadOnly Property FrequentVisitor() As Boolean Get Return No > 6 End Get End Property End Class
- Marked As Answer by Sheldon _XiaoModerator Sunday, September 09, 2012 4:34 PM
-
Monday, September 03, 2012 5:16 AMModerator
Hi eugzl,
As I said before, if you use " myListBox.DataContext = Me.cvCustomeEntry", and then set ItemsSource={Binding}, your ListBox will generate by binding, you cannot use ListBox.Items.Add() to add your item any more, you have to do add/remove with datasource, WPF is different from winform, you should learn more about binding, and what is WPF UI, and what is Data source.
Best regards,
Sheldon _Xiao[MSFT]
MSDN Community Support | Feedback to us
Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
-
Sunday, September 09, 2012 4:35 PMModerator
Hi eugzl,
I am marking your issue as "Answered", if you need further discusstion, please let us know.
Best regards,
Sheldon _Xiao[MSFT]
MSDN Community Support | Feedback to us
Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
-
Tuesday, September 11, 2012 8:34 PMModerator
> with WPF you are better off leveraging Data Binding
I concur with Techno and an excellent point at that...for WPF is data binding in an asyc fashion. Any Silverlight developer will tell you that, the sooner a WPF developer grasps that async methodology of data binding; the easier his/her life will be.
Thanks Techno for taking the time to create that example. :-)
William Wegerson (www.OmegaCoder.Com)
-
Tuesday, September 11, 2012 9:43 PM
Hey OmegaMan;
What does async binding mean?
JP Cowboy Coders Unite!
-
Wednesday, September 12, 2012 3:47 PMModerator
> async binding mean
My bad...It is a philosophy for me in which I think of as "Async Binding".
For one sets up binding to a binding target in WPF as shown above. The when and the how that data gets to the target is transparent for a WPF coder. But a coder doing Silverlight does/uses the same binding mechanisim, but has to be cognizant of the acquisition of data and has to use actual asynchronous calls to fill the target of the binding whereas the WPF doesn't necessarily need to depending on circumstance.
To Xaml code, the binding is the same whether the data is called asychronously or not and doesn't do the process on screen til the InotifyPropertyChanged event occurs; that event in my mind is a defacto asynchronous system which I think of as Async Binding.
If one designs systems where the timing of the binding is inconsequential, an async fashion, it leads to an easier way of coding; just as the difference between Winforms and the WPF way.
I should stop thinking out loud and stick to standard nomenclature. :-)
William Wegerson (www.OmegaCoder.Com)
- Edited by OmegaManMVP, Moderator Wednesday, September 12, 2012 3:51 PM
-
Wednesday, September 12, 2012 7:08 PM
Indeed you are correct that the INotifyEvent by virtue of being an event is Asynchronous in nature. This is one of the tricks I use when I design models "Use an event to signal when data is ready" Because a Viewmodel can know the model, there's no problem hooking up an event listener in the ViewModel to the Model's DataReadyEvent! This is push based, but I've even tried RX with very good results as well.
JP Cowboy Coders Unite!

