0
votes

I have a view with a ListBox databound to an Observable Collection of Person. In the same view, I have a Button. What I'd like to do is select an item from the ListBox and have the selected item's DataTemplate replaced from "Person" to "PersonEdit" when I click on the button.

I've looked at TemplateSelector, Triggers, etc, but can't seem to get anything to work.

Any ideas?

<DataTemplate x:Key="Person">
        <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>

    <DataTemplate x:Key="PersonEdit">
        <TextBox Text="{Binding Path=Name}"/>
    </DataTemplate>

<ListBox
        x:Name="lbPersons"
        Grid.Row="0"
        VerticalAlignment="Stretch"
        Margin="5"
        ItemsSource="{Binding Path=Persons}"
        ItemTemplate="{StaticResource ResourceKey=Person}"
        >
    </ListBox>

<Button
        Grid.Row="1"
        VerticalAlignment="Center"
        HorizontalAlignment="Center"
        Content="Add Person" Command="{Binding AddPerson}"/>
1

1 Answers

0
votes

I think the best option would be to add a property to your Person model to tell the UI that you are editing and use that property change the Template

Here is a rough working example of what I mean, in this example when you set a Person item to IsEditing it will change the Template to PersonEdit otherwise it will set the Template Person

Xaml:

<Window x:Class="WpfApplication7.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="399" Width="464" Name="UI" >

    <Window.Resources>
        <DataTemplate x:Key="Person">
            <TextBlock Text="{Binding Name}"/>
        </DataTemplate>

        <DataTemplate x:Key="PersonEdit">
            <TextBox Text="{Binding Name}"/>
        </DataTemplate>

        <Style TargetType="{x:Type ListBoxItem}" x:Key="PersonStyle">
            <Setter Property="ContentTemplate" Value="{StaticResource Person}" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsEditing}" Value="True">
                    <Setter Property="ContentTemplate" Value="{StaticResource PersonEdit}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>

    </Window.Resources>

    <Grid DataContext="{Binding ElementName=UI}"> 
        <ListBox Margin="5,5,5,30"
                 ItemsSource="{Binding Persons}"
                 SelectedItem="{Binding SelectedPerson}"
                 ItemContainerStyle="{StaticResource PersonStyle}" />

        <Button Margin="5,333,369,5" Content="Add Person" Click="Button_Click" />
    </Grid>
</Window>

Code:

public partial class MainWindow : Window
{

    private Person _selectedPerson;
    private ObservableCollection<Person> _persons = new ObservableCollection<Person>();

    public MainWindow()
    {
        InitializeComponent();
        Persons.Add(new Person { Name = "Stack" });
        Persons.Add(new Person { Name = "Overflow" });
    }

    public ObservableCollection<Person> Persons
    {
        get { return _persons; }
        set { _persons = value; }
    }

    public Person SelectedPerson
    {
        get { return _selectedPerson; }
        set { _selectedPerson = value; }
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        SelectedPerson.IsEditing = true;
    }

}

Person class:

public class Person : INotifyPropertyChanged
{
    private string _name;
    private bool _isEditing;

    public string Name
    {
        get { return _name; }
        set { _name = value; NotifyPropertyChanged("Name"); }
    }

    public bool IsEditing
    {
        get { return _isEditing; }
        set { _isEditing = value; NotifyPropertyChanged("IsEditing"); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}