I have a ListView which is bound to an ObservableCollection
I have added a DataTemplate to a ListView to bind item with TextBox in purpose to Rename selectedItem using Rename from ContextMenu:
View
<ListView DockPanel.Dock="Left"
Background="MidnightBlue"
Width="140"
SelectedItem="{Binding SelectedNotebook, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding Notebooks}"
x:Name="notebooksList"
SelectionChanged="notebooksList_SelectionChanged"
SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<uc:DisplayNotebook Notebook="{Binding}">
<uc:DisplayNotebook.ContextMenu>
<ContextMenu>
<MenuItem Header="Rename"
Command="{Binding Source={StaticResource vm}, Path=EditCommand}"
CommandParameter="{Binding SelectedNotebook}"/>
<MenuItem Header="Delete"
Command="{Binding Source={StaticResource vm}, Path=DeleteNotebookCommand}"
CommandParameter="{Binding SelectedNotebook}"/>
</ContextMenu>
</uc:DisplayNotebook.ContextMenu>
</uc:DisplayNotebook>
<TextBox Text="{Binding Name, Mode=TwoWay}"
Visibility="{Binding Source={StaticResource vm}, Path=IsVisible}"
x:Name="notebookTextBox">
<i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus">
<i:InvokeCommandAction Command="{Binding Source={StaticResource vm}, Path=EndEditingCommand}"
CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ViewModel
public async void StopEditingNotebook(Notebook notebook)
{
IsVisible = Visibility.Collapsed;
await DatabaseHelper.Update(notebook);
GetNotebooks();
}
public async void StopEditingNote (Note note)
{
IsVisible = Visibility.Collapsed;
await DatabaseHelper.Update(note);
GetNotes();
}
Commands
public class EndEditingCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public NotesVM ViewModel { get; set; }
public EndEditingCommand(NotesVM vm)
{
ViewModel = vm;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
Notebook notebook = parameter as Notebook;
if (notebook != null)
ViewModel.StopEditingNotebook(notebook);
}
}
public class EditCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public NotesVM ViewModel { get; set; }
public EditCommand(NotesVM vm)
{
ViewModel = vm;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
ViewModel.StartEditing();
}
}
I'd like to Rename only one item at once by popping up one TextBox instead of all TextBoxes in the same time(this what is happening currently due to bound TextBox in DataTemplate).
I was wondering about finding an ID of selectedItem and then somehow display only this particular TextBox.
Do you have any ideas on this matter? Thanks for help in advance
You can use a
MultiDataTriggerto toggle theVisibilityof theTextBox. The conditions areIsSelectedandIsVisiblefrom your view model.Alternatively (recommended), spend your item model an
IsEditEnabledproperty (or move and rename theIsVisibleproperty to the item model).Currently, every item binds to the same
IsVisibleproperty of the sameViewModelinstance.Instead, each item must bind to its own property (that's why the property should be defined in the item model).
Note, a member named with the prefix "is" is expected to return a boolean. In your case it would be semantically correct to name the property
Visibilityand notIsVisible.Additionally, the
CommandParameterbinding inside theContextMenulooks wrong too. It must be