Denis Yakovenko
Denis Yakovenko

Reputation: 3535

WPF How to make listbox items editable?

I need to add the "edit selected item" functionality to my listbox. Basically I need either of two:

Problems I encountered:

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

Answers (2)

Noctis
Noctis

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

Filip
Filip

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

Related Questions