If I understood correctly what you are trying to do, the following view model and xaml can be useful.
This sample shows a toggle Button for each item to enable editing the item name. When pressed a TextBox with two buttons (Ok, Cancel) is shown, if Ok button is pressed then item's name is changed, if cancel button is pressed current name is restored.
Helper class that exposes a command that executes a delegate action:
struct DelegateCommand: public BaseCommand
{
typedef Delegate<void (BaseComponent*)> CommandAction;
CommandAction action;
DelegateCommand(const CommandAction& action_): action(action_) { }
NsBool CanExecute(BaseComponent* ) const override { return true; }
void Execute(BaseComponent* param) const override { action(param); }
NS_IMPLEMENT_INLINE_REFLECTION_(DelegateCommand, BaseCommand)
};
View model for each item:
NS_DECLARE_SYMBOL(Name)
NS_DECLARE_SYMBOL(IsEditingName)
NS_DECLARE_SYMBOL(EditedName)
NS_DECLARE_SYMBOL(AcceptName)
NS_DECLARE_SYMBOL(DiscardName)
struct DataItem: public BaseComponent, public INotifyPropertyChanged
{
DataItem(const NsChar* n): name(n), isEditingName(false), editedName(n)
{
acceptName = *new DelegateCommand(MakeDelegate(this, &DataItem::OnAcceptName));
discardName = *new DelegateCommand(MakeDelegate(this, &DataItem::OnDiscardName));
}
PropertyChangedEventHandler& PropertyChanged() { return changed; }
const NsChar* GetName() const { return name.c_str(); }
NsBool GetIsEditingName() const { return isEditingName; }
void SetIsEditingName(NsBool value) { if (isEditingName != value) { isEditingName = value; Changed(NSS(IsEditingName)); } }
const NsChar* GetEditedName() const { return editedName.c_str(); }
void SetEditedName(const NsChar* value) { if (editedName != value) { editedName = value; Changed(NSS(Name)); } }
ICommand* GetAcceptName() const { return acceptName.GetPtr(); }
ICommand* GetDiscardName() const { return discardName.GetPtr(); }
NS_IMPLEMENT_INTERFACE_FIXUP
private:
void Changed(NsSymbol prop) { changed(this, PropertyChangedEventArgs(prop)); }
void OnAcceptName(BaseComponent*)
{
name = editedName; Changed(NSS(Name));
SetIsEditingName(false);
}
void OnDiscardName(BaseComponent*)
{
editedName = name; Changed(NSS(EditedName));
SetIsEditingName(false);
}
private:
PropertyChangedEventHandler changed;
NsString name;
NsString editedName;
NsBool isEditingName;
Ptr<DelegateCommand> acceptName;
Ptr<DelegateCommand> discardName;
NS_IMPLEMENT_INLINE_REFLECTION(DataItem, BaseComponent)
{
NsImpl<INotifyPropertyChanged>();
NsProp("Name", &DataItem::GetName);
NsProp("IsEditingName", &DataItem::GetIsEditingName, &DataItem::SetIsEditingName);
NsProp("EditedName", &DataItem::GetEditedName, &DataItem::SetEditedName);
NsProp("AcceptName", &DataItem::GetAcceptName);
NsProp("DiscardName", &DataItem::GetDiscardName);
}
};
Code-behind class for this sample:
struct ListBoxEditItem: public Grid
{
TestGrid()
{
InitializeComponent();
// test data!!!
Ptr<Collection> items = *new Collection();
Ptr<DataItem> item = *new DataItem("John");
items->Add(item.GetPtr());
item = *new DataItem("Mike");
items->Add(item.GetPtr());
item = *new DataItem("Luke");
items->Add(item.GetPtr());
SetDataContext(items.GetPtr());
}
private:
void InitializeComponent()
{
GUI::LoadComponent(this, "ListBoxEditItem.xaml");
}
NS_IMPLEMENT_INLINE_REFLECTION(ListBoxEditItem, Grid)
{
NsMeta<TypeId>("ListBoxEditItem");
}
};
void RegisterComponents() const
{
//...
NsRegisterComponent<ListBoxEditItem>();
}
Associated Xaml for the ListBoxEditItem class:
<Grid x:Class="ListBoxEditItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid.Resources>
<DataTemplate x:Key="itemTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Margin="3,0,4,0"/>
<ToggleButton Grid.Column="1" Grid.ColumnSpan="2" Content="Edit Name" IsChecked="{Binding IsEditingName}"/>
<Rectangle x:Name="editBg" Grid.ColumnSpan="3" Fill="Pink" Visibility="Hidden" Margin="-4"/>
<TextBox x:Name="editName" Text="{Binding EditedName}" Margin="0,0,4,0" Visibility="Hidden"/>
<Button x:Name="acceptName" Grid.Column="1" Content="OK" Command="{Binding AcceptName}" Visibility="Hidden"/>
<Button x:Name="discardName" Grid.Column="2" Content="Cancel" Command="{Binding DiscardName}" Visibility="Hidden"/>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsEditingName}" Value="True">
<Setter TargetName="editBg" Property="Visibility" Value="Visible"/>
<Setter TargetName="editName" Property="Visibility" Value="Visible"/>
<Setter TargetName="acceptName" Property="Visibility" Value="Visible"/>
<Setter TargetName="discardName" Property="Visibility" Value="Visible"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Grid.Resources>
<ListBox ItemsSource="{Binding}" ItemTemplate="{StaticResource itemTemplate}"
Width="300" Height="200"/>
</Grid>