Reputation: 3535
I need to add the "edit selected item" functionality to my listbox. Basically I need either of two:
Ctrl+Click on list item and it magically becomes an editable textbox or something and when edited update the data in the database.
Press the "Edit" Button under my ListBox, open the new Edit Window, edit the data there, update the database and update the ListBox when the Edit Window is closed.
Problems I encountered:
I want to have the first variant of the solution but I really don't know how to implement that.
Implementing the second variant I didn't get how should I update the ListBox after editing the selected item in a new Window.
Here's my XAML of ListBox:
<Grid>
<ListBox x:Name="LstQueries" HorizontalAlignment="Left" Height="228" VerticalAlignment="Top" Width="482" FontFamily="HelveticaNeueCyr" FontSize="16" ItemsSource="{Binding Queries}" MouseDoubleClick="LstQueries_MouseDoubleClick">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Label Content="{Binding Name}" FontWeight="Medium" FontSize="18" FontFamily="Helvetica"/>
<TextBlock Text="{Binding Text}" FontSize="16" FontFamily="Helvetica"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button x:Name="BtnEdit" Content="Edit" HorizontalAlignment="Left" Margin="0,228,0,0" VerticalAlignment="Top" Width="482" Height="43" Click="BtnEdit_Click"/>
</Grid>
And here's what my Edit Window XAML like:
<Grid>
<TextBox x:Name="TxtName" HorizontalAlignment="Left" Height="23" Margin="99,13,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="183" FontFamily="HelveticaNeueCyr" FontSize="16"/>
<Label Content="Name:" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" FontFamily="HelveticaNeueCyr" FontSize="16"/>
<TextBox x:Name="TxtText" HorizontalAlignment="Left" Height="116" Margin="65,45,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="217" FontFamily="HelveticaNeueCyr" FontSize="16"/>
<Label Content="Text:" HorizontalAlignment="Left" Margin="10,86,0,0" VerticalAlignment="Top" FontFamily="HelveticaNeueCyr" FontSize="16" Height="27" Width="50"/>
<Button x:Name="BtnSave" Content="Save" HorizontalAlignment="Left" Margin="10,166,0,0" VerticalAlignment="Top" Width="132" Height="33"/>
<Button x:Name="BtnCancel" Content="Cancel" HorizontalAlignment="Left" Margin="150,166,0,0" VerticalAlignment="Top" Width="132" Height="33" Click="BtnCancel_Click"/>
</Grid>
And here's how I access the SelectedItem in the ListBox:
if (LstQueries.SelectedIndex < 0) return;
dynamic item = LstQueries.SelectedItem as dynamic;
string name = item.Name;
string text = item.Text;
'Queries' that are binded to the listBox is the ObservableCollection<Query>
where Query
looks like this:
public class Query
{
public string Id { get; set; }
public string Name { get; set; }
public string Text { get; set; }
public string Autoschool { get; set; }
}
So, could you help me please with implementing either of solutions?
Upvotes: 1
Views: 5098
Reputation: 11763
You could tackle this in different ways.
In a project I wrote once, I wanted to have a double click on an item open up the edit window for that item.
I've opted to go with the i.Interaction.Triggers
. The specific code looks like :
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<Command:EventToCommand Command="{Binding EditExercise_Command}"
CommandParameter="{Binding ElementName=LastExercises_ListView
,Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
Now, whenever I double click an item, it opens the window to edit it. This was using MVVM, so I didn't want to have code in my code behind.
You'll have to reference this dll: system.windows.interactivity.dll
, and you'll probably want to read a bit about their usage. Here's an article about that.
Here's the full listbox code (the relevant bits at least):
<ListBox x:Name="..."
ItemsSource="{Binding FilteredCollection}"
SelectedItem="{Binding SelectedExercise, UpdateSourceTrigger=PropertyChanged}"
...
>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header ="Edit Exercise"
Command="{Binding EditExercise_Command}"
CommandParameter="{Binding SelectedExercise}"
/>
<MenuItem Header ="Delete Exercise"
Command="{Binding DeleteExercise_Command}"
CommandParameter="{Binding SelectedExercise}"
/>
</ContextMenu>
</ListBox.ContextMenu>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<Command:EventToCommand Command="{Binding EditExercise_Command}"
CommandParameter="{Binding ElementName=LastExercises_ListView
, Path=SelectedItem}"
/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
You also get extra right click menu options in case you don't want to double click, or if you want to delete that item (with a different command)
Upvotes: 2
Reputation: 1864
Why use dynamic? You can cast SelectedItem
to Query
without problem. Once you have it, all you need to do is load properties into your Edit Window and handle editing here.
Your Query needs to implement INotifyPropertyChanged
. Otherwise you won't see changes in ListBox
(because the control is not aware of them). https://msdn.microsoft.com/en-us/library/vstudio/ms229614(v=vs.100).aspx
Also, it would be easier to use Binding
. Don't forget to set the Binding mode to TwoWay
so your properties get updated once you change them. http://blog.scottlogic.com/2012/04/20/everything-you-wanted-to-know-about-databinding-in-wpf-silverlight-and-wp7-part-two.html
For your window. Prepare there single Query
property (named SelectedQuery for example) to which you set your selected instance. You can then bind your TextBoxes (in window) using something like this: Text="{Binding SelectedQuery.Name, Mode="TwoWay"}"
. If you have corretly implemented INotifyPropertyChanged
changing text in your window should immediately change it in your ListView
.
Upvotes: 1