Inline editing TextBlock in a ListBox with Data Template (WPF)











up vote
9
down vote

favorite
10












Using WPF, I have a ListBox control with a DataTemplate inside it. The relevant XAML code is shown below:



<ListBox Name="_todoList" Grid.Row="1" BorderThickness="2"
Drop="todoList_Drop" AllowDrop="True"
HorizontalContentAlignment="Stretch"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
AlternationCount="2">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0" Checked="CheckBox_Check" />
<TextBlock Name="descriptionBlock"
Grid.Column="1"
Text="{Binding Description}"
Cursor="Hand" FontSize="14"
ToolTip="{Binding Description}"
MouseDown="TextBlock_MouseDown" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>


What I am trying to do is make the TextBlock respond to a (double)click which turns it into a TextBox. The user can then edit the description, and press return or change focus to make the change.



I have tried adding a TextBox element in the same position as the TextBlock and making its visiblity Collapsed, but I don't know how to navigate to the right TextBox when the user has clicked on a TextBlock. That is, I know the user has clicked on a certain TextBlock, now which TextBox do I show?



Any help would be appreciated greatly,



-Ko9










share|improve this question
























  • As a tip, rather than using pre tags and explicitly escaping angle brackets, you can just paste XAML directly into the editor and use the 101010 button to format it as code.
    – itowlson
    Jan 18 '10 at 20:32















up vote
9
down vote

favorite
10












Using WPF, I have a ListBox control with a DataTemplate inside it. The relevant XAML code is shown below:



<ListBox Name="_todoList" Grid.Row="1" BorderThickness="2"
Drop="todoList_Drop" AllowDrop="True"
HorizontalContentAlignment="Stretch"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
AlternationCount="2">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0" Checked="CheckBox_Check" />
<TextBlock Name="descriptionBlock"
Grid.Column="1"
Text="{Binding Description}"
Cursor="Hand" FontSize="14"
ToolTip="{Binding Description}"
MouseDown="TextBlock_MouseDown" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>


What I am trying to do is make the TextBlock respond to a (double)click which turns it into a TextBox. The user can then edit the description, and press return or change focus to make the change.



I have tried adding a TextBox element in the same position as the TextBlock and making its visiblity Collapsed, but I don't know how to navigate to the right TextBox when the user has clicked on a TextBlock. That is, I know the user has clicked on a certain TextBlock, now which TextBox do I show?



Any help would be appreciated greatly,



-Ko9










share|improve this question
























  • As a tip, rather than using pre tags and explicitly escaping angle brackets, you can just paste XAML directly into the editor and use the 101010 button to format it as code.
    – itowlson
    Jan 18 '10 at 20:32













up vote
9
down vote

favorite
10









up vote
9
down vote

favorite
10






10





Using WPF, I have a ListBox control with a DataTemplate inside it. The relevant XAML code is shown below:



<ListBox Name="_todoList" Grid.Row="1" BorderThickness="2"
Drop="todoList_Drop" AllowDrop="True"
HorizontalContentAlignment="Stretch"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
AlternationCount="2">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0" Checked="CheckBox_Check" />
<TextBlock Name="descriptionBlock"
Grid.Column="1"
Text="{Binding Description}"
Cursor="Hand" FontSize="14"
ToolTip="{Binding Description}"
MouseDown="TextBlock_MouseDown" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>


What I am trying to do is make the TextBlock respond to a (double)click which turns it into a TextBox. The user can then edit the description, and press return or change focus to make the change.



I have tried adding a TextBox element in the same position as the TextBlock and making its visiblity Collapsed, but I don't know how to navigate to the right TextBox when the user has clicked on a TextBlock. That is, I know the user has clicked on a certain TextBlock, now which TextBox do I show?



Any help would be appreciated greatly,



-Ko9










share|improve this question















Using WPF, I have a ListBox control with a DataTemplate inside it. The relevant XAML code is shown below:



<ListBox Name="_todoList" Grid.Row="1" BorderThickness="2"
Drop="todoList_Drop" AllowDrop="True"
HorizontalContentAlignment="Stretch"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
AlternationCount="2">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0" Checked="CheckBox_Check" />
<TextBlock Name="descriptionBlock"
Grid.Column="1"
Text="{Binding Description}"
Cursor="Hand" FontSize="14"
ToolTip="{Binding Description}"
MouseDown="TextBlock_MouseDown" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>


What I am trying to do is make the TextBlock respond to a (double)click which turns it into a TextBox. The user can then edit the description, and press return or change focus to make the change.



I have tried adding a TextBox element in the same position as the TextBlock and making its visiblity Collapsed, but I don't know how to navigate to the right TextBox when the user has clicked on a TextBlock. That is, I know the user has clicked on a certain TextBlock, now which TextBox do I show?



Any help would be appreciated greatly,



-Ko9







c# wpf xaml listbox datatemplate






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Sep 16 '11 at 17:40









Dave Clemmer

2,967114371




2,967114371










asked Jan 18 '10 at 20:18









Ko9

89138




89138












  • As a tip, rather than using pre tags and explicitly escaping angle brackets, you can just paste XAML directly into the editor and use the 101010 button to format it as code.
    – itowlson
    Jan 18 '10 at 20:32


















  • As a tip, rather than using pre tags and explicitly escaping angle brackets, you can just paste XAML directly into the editor and use the 101010 button to format it as code.
    – itowlson
    Jan 18 '10 at 20:32
















As a tip, rather than using pre tags and explicitly escaping angle brackets, you can just paste XAML directly into the editor and use the 101010 button to format it as code.
– itowlson
Jan 18 '10 at 20:32




As a tip, rather than using pre tags and explicitly escaping angle brackets, you can just paste XAML directly into the editor and use the 101010 button to format it as code.
– itowlson
Jan 18 '10 at 20:32












4 Answers
4






active

oldest

votes

















up vote
15
down vote



accepted










What I've done in these situations is used the XAML hierarchy to determine which element to show/hide. Something along the lines of:



<Grid>
<TextBlock MouseDown="txtblk_MouseDown" />
<TextBox LostFocus="txtbox_LostFocus" Visibility="Collapsed" />
</Grid>


with the code:



protected void txtblk_MouseDown(object sender, MouseButtonEventArgs e)
{
TextBox txt = (TextBox)((Grid)((TextBlock)sender).Parent).Children[1];
txt.Visibility = Visibility.Visible;
((TextBlock)sender).Visibility = Visibility.Collapsed;
}

protected void txtbox_LostFocus(object sender, RoutedEventArgs e)
{
TextBlock tb = (TextBlock)((Grid)((TextBox)sender).Parent).Children[0];
tb.Text = ((TextBox)sender).Text;
tb.Visibility = Visibility.Visible;
((TextBox)sender).Visibility = Visibility.Collapsed;
}


I always turn stuff like this that I'm going to reuse into a UserControl, which I can add additional error handling to, and guarantee that the Grid will only contain two items, and the order of them will never change.



EDIT: Additionally, turning this into a UserControl allows you to create a Text property for each instantiation, so you can name each one and reference the text directly without fishing for the current value through the ((TextBox)myGrid.Children[1]).Text casting. This will make your code much more efficient and clean. If you make it into a UserControl, you can also name the TextBlock and TextBox elements, so no casting is needed at all.






share|improve this answer























  • this may sound odd, could you edit your answer... I clicked up prematurely, then removed my vote, because I wasnt sure if this was what I was after. I then tried to post an up vote again because it was what I needed and Stack Overflow says I cannot vote on this post unless it was edited. hence the request. Cheers, very useful post as it turned out.
    – Luke Duddridge
    Jul 5 '10 at 13:40


















up vote
13
down vote













Refer to the Nathan Wheeler's code snippet, the following codes are complete UserControl source that I coded yesterday.
Especially, Binding issues are addressed.
Nathan's code is easy to follow, but needs some aid in order to work with databound text.



ClickToEditTextboxControl.xaml.cs



public partial class ClickToEditTextboxControl : UserControl
{
public ClickToEditTextboxControl()
{
InitializeComponent();
}

public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}

// Using a DependencyProperty as the backing store for Text. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(ClickToEditTextboxControl), new UIPropertyMetadata());

private void textBoxName_LostFocus(object sender, RoutedEventArgs e)
{
var txtBlock = (TextBlock)((Grid)((TextBox)sender).Parent).Children[0];

txtBlock.Visibility = Visibility.Visible;
((TextBox)sender).Visibility = Visibility.Collapsed;
}

private void textBlockName_MouseDown(object sender, MouseButtonEventArgs e)
{
var grid = ((Grid) ((TextBlock) sender).Parent);
var tbx = (TextBox)grid.Children[1];
((TextBlock)sender).Visibility = Visibility.Collapsed;
tbx.Visibility = Visibility.Visible;

this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
}

private void TextBoxKeyDown(object sender, KeyEventArgs e)
{
if (e == null)
return;

if (e.Key == Key.Return)
{
textBoxName_LostFocus(sender, null);
}
}
}


ClickToEditTextboxControl.xaml



<UserControl x:Class="Template.ClickToEditTextboxControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Name="root"
d:DesignHeight="30" d:DesignWidth="100">
<Grid>
<TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" MouseDown="textBlockName_MouseDown" />
<TextBox Name="textBoxName" Text="{Binding ElementName=root, Path=Text, UpdateSourceTrigger=PropertyChanged}" Visibility="Collapsed" LostFocus="textBoxName_LostFocus" KeyDown ="TextBoxKeyDown"/>
</Grid>
</UserControl>


And, finally, you can use this control in the XAML as below:



<Template1:ClickToEditTextboxControl Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="40" Height="23" />


Note that Mode=TwoWay, UpdateSourceTrigger=PropertyChanged is set. It enables to change the binded value in every type.






share|improve this answer























  • Thanks for this solution, I use it via DataTemplate for my ListBox, but the new value does not get updated in the source. The ItemsSource is of type ObservableCollection<string>. Any ideas?
    – Nicolas
    Nov 8 at 12:10


















up vote
4
down vote













The ideal way to do this would be to create a ClickEditableTextBlock control, which by default renders as a TextBlock but shows a TextBox when the user clicks it. Because any given ClickEditableTextBlock has only one TextBlock and one TextBox, you don't have the matching issue. Then you use a ClickEditableTextBlock instead of separate TextBlocks and TextBoxes in your DataTemplate.



This has the side benefit of encapsulating the functionality in a control so you don't pollute your main window code-behind with the edit behaviour, plus you can easily reuse it in other templates.





If this sounds like too much effort, you can use Tag or an attached property to associate each TextBlock with a TextBox:



<DataTemplate>
<StackPanel>
<TextBlock Text="whatever"
MouseDown="TextBlock_MouseDown"
Tag="{Binding ElementName=tb}" />
<TextBox Name="tb" />
</StackPanel>
</DataTemplate>


Note the use of {Binding ElementName=tb} on the Tag to refer to the TextBox named tb.



And in your code-behind:



private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
FrameworkElement textBlock = (FrameworkElement)sender;
TextBox editBox = (TextBox)(textBlock.Tag);
editBox.Text = "Wow!"; // or set visible or whatever
}


(To avoid the use of the nasty Tag property, you could define a custom attached property to carry the TextBox binding, but for brevity I'm not showing that.)






share|improve this answer






























    up vote
    1
    down vote













    If I may supplement, in order to cover the (double) part of the original question, in Youngjae's reply you make the following replacement in the xaml file:



    <TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" MouseDown="textBlockName_MouseDown" />


    is replaced with



    <TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" >
    <TextBlock.InputBindings>
    <MouseBinding Gesture="LeftDoubleCLick" Command="{StaticResource cmdEditTextblock}"/>
    </TextBlock.InputBindings>
    </TextBlock>


    adding also the proper RoutedCommand in UserControl.Resources



    <UserControl.Resources>
    <RoutedCommand x:Key="cmdEditTextblock"/>
    </UserControl.Resources>


    and a CommandBinding in UserControl.CommandBindings



    <UserControl.CommandBindings>
    <CommandBinding Command="{StaticResource cmdEditTextblock}"
    Executed="CmdEditTextblock_Executed"/>
    </UserControl.CommandBindings>


    Also in the code behind file:



    private void textBlockName_MouseDown(object sender, MouseButtonEventArgs e)
    {
    var grid = ((Grid) ((TextBlock) sender).Parent);
    var tbx = (TextBox)grid.Children[1];
    ((TextBlock)sender).Visibility = Visibility.Collapsed;
    tbx.Visibility = Visibility.Visible;
    this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
    }


    is replaced by



    private void CmdEditTextblock_Executed(object sender, ExecutedRoutedEventArgs e)
    {
    var grid = ((Grid)((TextBlock)e.OriginalSource).Parent);
    var tbx = (TextBox)grid.Children[1];
    ((TextBlock)e.OriginalSource).Visibility = Visibility.Collapsed;
    tbx.Visibility = Visibility.Visible;
    this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
    }


    In case some people want to have left doubleclick as input gesture, like I did...






    share|improve this answer





















      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f2088909%2finline-editing-textblock-in-a-listbox-with-data-template-wpf%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      15
      down vote



      accepted










      What I've done in these situations is used the XAML hierarchy to determine which element to show/hide. Something along the lines of:



      <Grid>
      <TextBlock MouseDown="txtblk_MouseDown" />
      <TextBox LostFocus="txtbox_LostFocus" Visibility="Collapsed" />
      </Grid>


      with the code:



      protected void txtblk_MouseDown(object sender, MouseButtonEventArgs e)
      {
      TextBox txt = (TextBox)((Grid)((TextBlock)sender).Parent).Children[1];
      txt.Visibility = Visibility.Visible;
      ((TextBlock)sender).Visibility = Visibility.Collapsed;
      }

      protected void txtbox_LostFocus(object sender, RoutedEventArgs e)
      {
      TextBlock tb = (TextBlock)((Grid)((TextBox)sender).Parent).Children[0];
      tb.Text = ((TextBox)sender).Text;
      tb.Visibility = Visibility.Visible;
      ((TextBox)sender).Visibility = Visibility.Collapsed;
      }


      I always turn stuff like this that I'm going to reuse into a UserControl, which I can add additional error handling to, and guarantee that the Grid will only contain two items, and the order of them will never change.



      EDIT: Additionally, turning this into a UserControl allows you to create a Text property for each instantiation, so you can name each one and reference the text directly without fishing for the current value through the ((TextBox)myGrid.Children[1]).Text casting. This will make your code much more efficient and clean. If you make it into a UserControl, you can also name the TextBlock and TextBox elements, so no casting is needed at all.






      share|improve this answer























      • this may sound odd, could you edit your answer... I clicked up prematurely, then removed my vote, because I wasnt sure if this was what I was after. I then tried to post an up vote again because it was what I needed and Stack Overflow says I cannot vote on this post unless it was edited. hence the request. Cheers, very useful post as it turned out.
        – Luke Duddridge
        Jul 5 '10 at 13:40















      up vote
      15
      down vote



      accepted










      What I've done in these situations is used the XAML hierarchy to determine which element to show/hide. Something along the lines of:



      <Grid>
      <TextBlock MouseDown="txtblk_MouseDown" />
      <TextBox LostFocus="txtbox_LostFocus" Visibility="Collapsed" />
      </Grid>


      with the code:



      protected void txtblk_MouseDown(object sender, MouseButtonEventArgs e)
      {
      TextBox txt = (TextBox)((Grid)((TextBlock)sender).Parent).Children[1];
      txt.Visibility = Visibility.Visible;
      ((TextBlock)sender).Visibility = Visibility.Collapsed;
      }

      protected void txtbox_LostFocus(object sender, RoutedEventArgs e)
      {
      TextBlock tb = (TextBlock)((Grid)((TextBox)sender).Parent).Children[0];
      tb.Text = ((TextBox)sender).Text;
      tb.Visibility = Visibility.Visible;
      ((TextBox)sender).Visibility = Visibility.Collapsed;
      }


      I always turn stuff like this that I'm going to reuse into a UserControl, which I can add additional error handling to, and guarantee that the Grid will only contain two items, and the order of them will never change.



      EDIT: Additionally, turning this into a UserControl allows you to create a Text property for each instantiation, so you can name each one and reference the text directly without fishing for the current value through the ((TextBox)myGrid.Children[1]).Text casting. This will make your code much more efficient and clean. If you make it into a UserControl, you can also name the TextBlock and TextBox elements, so no casting is needed at all.






      share|improve this answer























      • this may sound odd, could you edit your answer... I clicked up prematurely, then removed my vote, because I wasnt sure if this was what I was after. I then tried to post an up vote again because it was what I needed and Stack Overflow says I cannot vote on this post unless it was edited. hence the request. Cheers, very useful post as it turned out.
        – Luke Duddridge
        Jul 5 '10 at 13:40













      up vote
      15
      down vote



      accepted







      up vote
      15
      down vote



      accepted






      What I've done in these situations is used the XAML hierarchy to determine which element to show/hide. Something along the lines of:



      <Grid>
      <TextBlock MouseDown="txtblk_MouseDown" />
      <TextBox LostFocus="txtbox_LostFocus" Visibility="Collapsed" />
      </Grid>


      with the code:



      protected void txtblk_MouseDown(object sender, MouseButtonEventArgs e)
      {
      TextBox txt = (TextBox)((Grid)((TextBlock)sender).Parent).Children[1];
      txt.Visibility = Visibility.Visible;
      ((TextBlock)sender).Visibility = Visibility.Collapsed;
      }

      protected void txtbox_LostFocus(object sender, RoutedEventArgs e)
      {
      TextBlock tb = (TextBlock)((Grid)((TextBox)sender).Parent).Children[0];
      tb.Text = ((TextBox)sender).Text;
      tb.Visibility = Visibility.Visible;
      ((TextBox)sender).Visibility = Visibility.Collapsed;
      }


      I always turn stuff like this that I'm going to reuse into a UserControl, which I can add additional error handling to, and guarantee that the Grid will only contain two items, and the order of them will never change.



      EDIT: Additionally, turning this into a UserControl allows you to create a Text property for each instantiation, so you can name each one and reference the text directly without fishing for the current value through the ((TextBox)myGrid.Children[1]).Text casting. This will make your code much more efficient and clean. If you make it into a UserControl, you can also name the TextBlock and TextBox elements, so no casting is needed at all.






      share|improve this answer














      What I've done in these situations is used the XAML hierarchy to determine which element to show/hide. Something along the lines of:



      <Grid>
      <TextBlock MouseDown="txtblk_MouseDown" />
      <TextBox LostFocus="txtbox_LostFocus" Visibility="Collapsed" />
      </Grid>


      with the code:



      protected void txtblk_MouseDown(object sender, MouseButtonEventArgs e)
      {
      TextBox txt = (TextBox)((Grid)((TextBlock)sender).Parent).Children[1];
      txt.Visibility = Visibility.Visible;
      ((TextBlock)sender).Visibility = Visibility.Collapsed;
      }

      protected void txtbox_LostFocus(object sender, RoutedEventArgs e)
      {
      TextBlock tb = (TextBlock)((Grid)((TextBox)sender).Parent).Children[0];
      tb.Text = ((TextBox)sender).Text;
      tb.Visibility = Visibility.Visible;
      ((TextBox)sender).Visibility = Visibility.Collapsed;
      }


      I always turn stuff like this that I'm going to reuse into a UserControl, which I can add additional error handling to, and guarantee that the Grid will only contain two items, and the order of them will never change.



      EDIT: Additionally, turning this into a UserControl allows you to create a Text property for each instantiation, so you can name each one and reference the text directly without fishing for the current value through the ((TextBox)myGrid.Children[1]).Text casting. This will make your code much more efficient and clean. If you make it into a UserControl, you can also name the TextBlock and TextBox elements, so no casting is needed at all.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jul 8 '10 at 13:41

























      answered Jan 18 '10 at 20:38









      Nathan Wheeler

      5,12022245




      5,12022245












      • this may sound odd, could you edit your answer... I clicked up prematurely, then removed my vote, because I wasnt sure if this was what I was after. I then tried to post an up vote again because it was what I needed and Stack Overflow says I cannot vote on this post unless it was edited. hence the request. Cheers, very useful post as it turned out.
        – Luke Duddridge
        Jul 5 '10 at 13:40


















      • this may sound odd, could you edit your answer... I clicked up prematurely, then removed my vote, because I wasnt sure if this was what I was after. I then tried to post an up vote again because it was what I needed and Stack Overflow says I cannot vote on this post unless it was edited. hence the request. Cheers, very useful post as it turned out.
        – Luke Duddridge
        Jul 5 '10 at 13:40
















      this may sound odd, could you edit your answer... I clicked up prematurely, then removed my vote, because I wasnt sure if this was what I was after. I then tried to post an up vote again because it was what I needed and Stack Overflow says I cannot vote on this post unless it was edited. hence the request. Cheers, very useful post as it turned out.
      – Luke Duddridge
      Jul 5 '10 at 13:40




      this may sound odd, could you edit your answer... I clicked up prematurely, then removed my vote, because I wasnt sure if this was what I was after. I then tried to post an up vote again because it was what I needed and Stack Overflow says I cannot vote on this post unless it was edited. hence the request. Cheers, very useful post as it turned out.
      – Luke Duddridge
      Jul 5 '10 at 13:40












      up vote
      13
      down vote













      Refer to the Nathan Wheeler's code snippet, the following codes are complete UserControl source that I coded yesterday.
      Especially, Binding issues are addressed.
      Nathan's code is easy to follow, but needs some aid in order to work with databound text.



      ClickToEditTextboxControl.xaml.cs



      public partial class ClickToEditTextboxControl : UserControl
      {
      public ClickToEditTextboxControl()
      {
      InitializeComponent();
      }

      public string Text
      {
      get { return (string)GetValue(TextProperty); }
      set { SetValue(TextProperty, value); }
      }

      // Using a DependencyProperty as the backing store for Text. This enables animation, styling, binding, etc...
      public static readonly DependencyProperty TextProperty =
      DependencyProperty.Register("Text", typeof(string), typeof(ClickToEditTextboxControl), new UIPropertyMetadata());

      private void textBoxName_LostFocus(object sender, RoutedEventArgs e)
      {
      var txtBlock = (TextBlock)((Grid)((TextBox)sender).Parent).Children[0];

      txtBlock.Visibility = Visibility.Visible;
      ((TextBox)sender).Visibility = Visibility.Collapsed;
      }

      private void textBlockName_MouseDown(object sender, MouseButtonEventArgs e)
      {
      var grid = ((Grid) ((TextBlock) sender).Parent);
      var tbx = (TextBox)grid.Children[1];
      ((TextBlock)sender).Visibility = Visibility.Collapsed;
      tbx.Visibility = Visibility.Visible;

      this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
      }

      private void TextBoxKeyDown(object sender, KeyEventArgs e)
      {
      if (e == null)
      return;

      if (e.Key == Key.Return)
      {
      textBoxName_LostFocus(sender, null);
      }
      }
      }


      ClickToEditTextboxControl.xaml



      <UserControl x:Class="Template.ClickToEditTextboxControl"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      mc:Ignorable="d"
      Name="root"
      d:DesignHeight="30" d:DesignWidth="100">
      <Grid>
      <TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" MouseDown="textBlockName_MouseDown" />
      <TextBox Name="textBoxName" Text="{Binding ElementName=root, Path=Text, UpdateSourceTrigger=PropertyChanged}" Visibility="Collapsed" LostFocus="textBoxName_LostFocus" KeyDown ="TextBoxKeyDown"/>
      </Grid>
      </UserControl>


      And, finally, you can use this control in the XAML as below:



      <Template1:ClickToEditTextboxControl Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="40" Height="23" />


      Note that Mode=TwoWay, UpdateSourceTrigger=PropertyChanged is set. It enables to change the binded value in every type.






      share|improve this answer























      • Thanks for this solution, I use it via DataTemplate for my ListBox, but the new value does not get updated in the source. The ItemsSource is of type ObservableCollection<string>. Any ideas?
        – Nicolas
        Nov 8 at 12:10















      up vote
      13
      down vote













      Refer to the Nathan Wheeler's code snippet, the following codes are complete UserControl source that I coded yesterday.
      Especially, Binding issues are addressed.
      Nathan's code is easy to follow, but needs some aid in order to work with databound text.



      ClickToEditTextboxControl.xaml.cs



      public partial class ClickToEditTextboxControl : UserControl
      {
      public ClickToEditTextboxControl()
      {
      InitializeComponent();
      }

      public string Text
      {
      get { return (string)GetValue(TextProperty); }
      set { SetValue(TextProperty, value); }
      }

      // Using a DependencyProperty as the backing store for Text. This enables animation, styling, binding, etc...
      public static readonly DependencyProperty TextProperty =
      DependencyProperty.Register("Text", typeof(string), typeof(ClickToEditTextboxControl), new UIPropertyMetadata());

      private void textBoxName_LostFocus(object sender, RoutedEventArgs e)
      {
      var txtBlock = (TextBlock)((Grid)((TextBox)sender).Parent).Children[0];

      txtBlock.Visibility = Visibility.Visible;
      ((TextBox)sender).Visibility = Visibility.Collapsed;
      }

      private void textBlockName_MouseDown(object sender, MouseButtonEventArgs e)
      {
      var grid = ((Grid) ((TextBlock) sender).Parent);
      var tbx = (TextBox)grid.Children[1];
      ((TextBlock)sender).Visibility = Visibility.Collapsed;
      tbx.Visibility = Visibility.Visible;

      this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
      }

      private void TextBoxKeyDown(object sender, KeyEventArgs e)
      {
      if (e == null)
      return;

      if (e.Key == Key.Return)
      {
      textBoxName_LostFocus(sender, null);
      }
      }
      }


      ClickToEditTextboxControl.xaml



      <UserControl x:Class="Template.ClickToEditTextboxControl"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      mc:Ignorable="d"
      Name="root"
      d:DesignHeight="30" d:DesignWidth="100">
      <Grid>
      <TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" MouseDown="textBlockName_MouseDown" />
      <TextBox Name="textBoxName" Text="{Binding ElementName=root, Path=Text, UpdateSourceTrigger=PropertyChanged}" Visibility="Collapsed" LostFocus="textBoxName_LostFocus" KeyDown ="TextBoxKeyDown"/>
      </Grid>
      </UserControl>


      And, finally, you can use this control in the XAML as below:



      <Template1:ClickToEditTextboxControl Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="40" Height="23" />


      Note that Mode=TwoWay, UpdateSourceTrigger=PropertyChanged is set. It enables to change the binded value in every type.






      share|improve this answer























      • Thanks for this solution, I use it via DataTemplate for my ListBox, but the new value does not get updated in the source. The ItemsSource is of type ObservableCollection<string>. Any ideas?
        – Nicolas
        Nov 8 at 12:10













      up vote
      13
      down vote










      up vote
      13
      down vote









      Refer to the Nathan Wheeler's code snippet, the following codes are complete UserControl source that I coded yesterday.
      Especially, Binding issues are addressed.
      Nathan's code is easy to follow, but needs some aid in order to work with databound text.



      ClickToEditTextboxControl.xaml.cs



      public partial class ClickToEditTextboxControl : UserControl
      {
      public ClickToEditTextboxControl()
      {
      InitializeComponent();
      }

      public string Text
      {
      get { return (string)GetValue(TextProperty); }
      set { SetValue(TextProperty, value); }
      }

      // Using a DependencyProperty as the backing store for Text. This enables animation, styling, binding, etc...
      public static readonly DependencyProperty TextProperty =
      DependencyProperty.Register("Text", typeof(string), typeof(ClickToEditTextboxControl), new UIPropertyMetadata());

      private void textBoxName_LostFocus(object sender, RoutedEventArgs e)
      {
      var txtBlock = (TextBlock)((Grid)((TextBox)sender).Parent).Children[0];

      txtBlock.Visibility = Visibility.Visible;
      ((TextBox)sender).Visibility = Visibility.Collapsed;
      }

      private void textBlockName_MouseDown(object sender, MouseButtonEventArgs e)
      {
      var grid = ((Grid) ((TextBlock) sender).Parent);
      var tbx = (TextBox)grid.Children[1];
      ((TextBlock)sender).Visibility = Visibility.Collapsed;
      tbx.Visibility = Visibility.Visible;

      this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
      }

      private void TextBoxKeyDown(object sender, KeyEventArgs e)
      {
      if (e == null)
      return;

      if (e.Key == Key.Return)
      {
      textBoxName_LostFocus(sender, null);
      }
      }
      }


      ClickToEditTextboxControl.xaml



      <UserControl x:Class="Template.ClickToEditTextboxControl"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      mc:Ignorable="d"
      Name="root"
      d:DesignHeight="30" d:DesignWidth="100">
      <Grid>
      <TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" MouseDown="textBlockName_MouseDown" />
      <TextBox Name="textBoxName" Text="{Binding ElementName=root, Path=Text, UpdateSourceTrigger=PropertyChanged}" Visibility="Collapsed" LostFocus="textBoxName_LostFocus" KeyDown ="TextBoxKeyDown"/>
      </Grid>
      </UserControl>


      And, finally, you can use this control in the XAML as below:



      <Template1:ClickToEditTextboxControl Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="40" Height="23" />


      Note that Mode=TwoWay, UpdateSourceTrigger=PropertyChanged is set. It enables to change the binded value in every type.






      share|improve this answer














      Refer to the Nathan Wheeler's code snippet, the following codes are complete UserControl source that I coded yesterday.
      Especially, Binding issues are addressed.
      Nathan's code is easy to follow, but needs some aid in order to work with databound text.



      ClickToEditTextboxControl.xaml.cs



      public partial class ClickToEditTextboxControl : UserControl
      {
      public ClickToEditTextboxControl()
      {
      InitializeComponent();
      }

      public string Text
      {
      get { return (string)GetValue(TextProperty); }
      set { SetValue(TextProperty, value); }
      }

      // Using a DependencyProperty as the backing store for Text. This enables animation, styling, binding, etc...
      public static readonly DependencyProperty TextProperty =
      DependencyProperty.Register("Text", typeof(string), typeof(ClickToEditTextboxControl), new UIPropertyMetadata());

      private void textBoxName_LostFocus(object sender, RoutedEventArgs e)
      {
      var txtBlock = (TextBlock)((Grid)((TextBox)sender).Parent).Children[0];

      txtBlock.Visibility = Visibility.Visible;
      ((TextBox)sender).Visibility = Visibility.Collapsed;
      }

      private void textBlockName_MouseDown(object sender, MouseButtonEventArgs e)
      {
      var grid = ((Grid) ((TextBlock) sender).Parent);
      var tbx = (TextBox)grid.Children[1];
      ((TextBlock)sender).Visibility = Visibility.Collapsed;
      tbx.Visibility = Visibility.Visible;

      this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
      }

      private void TextBoxKeyDown(object sender, KeyEventArgs e)
      {
      if (e == null)
      return;

      if (e.Key == Key.Return)
      {
      textBoxName_LostFocus(sender, null);
      }
      }
      }


      ClickToEditTextboxControl.xaml



      <UserControl x:Class="Template.ClickToEditTextboxControl"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      mc:Ignorable="d"
      Name="root"
      d:DesignHeight="30" d:DesignWidth="100">
      <Grid>
      <TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" MouseDown="textBlockName_MouseDown" />
      <TextBox Name="textBoxName" Text="{Binding ElementName=root, Path=Text, UpdateSourceTrigger=PropertyChanged}" Visibility="Collapsed" LostFocus="textBoxName_LostFocus" KeyDown ="TextBoxKeyDown"/>
      </Grid>
      </UserControl>


      And, finally, you can use this control in the XAML as below:



      <Template1:ClickToEditTextboxControl Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="40" Height="23" />


      Note that Mode=TwoWay, UpdateSourceTrigger=PropertyChanged is set. It enables to change the binded value in every type.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Nov 8 at 9:26


























      community wiki





      4 revs, 4 users 84%
      Youngjae













      • Thanks for this solution, I use it via DataTemplate for my ListBox, but the new value does not get updated in the source. The ItemsSource is of type ObservableCollection<string>. Any ideas?
        – Nicolas
        Nov 8 at 12:10


















      • Thanks for this solution, I use it via DataTemplate for my ListBox, but the new value does not get updated in the source. The ItemsSource is of type ObservableCollection<string>. Any ideas?
        – Nicolas
        Nov 8 at 12:10
















      Thanks for this solution, I use it via DataTemplate for my ListBox, but the new value does not get updated in the source. The ItemsSource is of type ObservableCollection<string>. Any ideas?
      – Nicolas
      Nov 8 at 12:10




      Thanks for this solution, I use it via DataTemplate for my ListBox, but the new value does not get updated in the source. The ItemsSource is of type ObservableCollection<string>. Any ideas?
      – Nicolas
      Nov 8 at 12:10










      up vote
      4
      down vote













      The ideal way to do this would be to create a ClickEditableTextBlock control, which by default renders as a TextBlock but shows a TextBox when the user clicks it. Because any given ClickEditableTextBlock has only one TextBlock and one TextBox, you don't have the matching issue. Then you use a ClickEditableTextBlock instead of separate TextBlocks and TextBoxes in your DataTemplate.



      This has the side benefit of encapsulating the functionality in a control so you don't pollute your main window code-behind with the edit behaviour, plus you can easily reuse it in other templates.





      If this sounds like too much effort, you can use Tag or an attached property to associate each TextBlock with a TextBox:



      <DataTemplate>
      <StackPanel>
      <TextBlock Text="whatever"
      MouseDown="TextBlock_MouseDown"
      Tag="{Binding ElementName=tb}" />
      <TextBox Name="tb" />
      </StackPanel>
      </DataTemplate>


      Note the use of {Binding ElementName=tb} on the Tag to refer to the TextBox named tb.



      And in your code-behind:



      private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
      {
      FrameworkElement textBlock = (FrameworkElement)sender;
      TextBox editBox = (TextBox)(textBlock.Tag);
      editBox.Text = "Wow!"; // or set visible or whatever
      }


      (To avoid the use of the nasty Tag property, you could define a custom attached property to carry the TextBox binding, but for brevity I'm not showing that.)






      share|improve this answer



























        up vote
        4
        down vote













        The ideal way to do this would be to create a ClickEditableTextBlock control, which by default renders as a TextBlock but shows a TextBox when the user clicks it. Because any given ClickEditableTextBlock has only one TextBlock and one TextBox, you don't have the matching issue. Then you use a ClickEditableTextBlock instead of separate TextBlocks and TextBoxes in your DataTemplate.



        This has the side benefit of encapsulating the functionality in a control so you don't pollute your main window code-behind with the edit behaviour, plus you can easily reuse it in other templates.





        If this sounds like too much effort, you can use Tag or an attached property to associate each TextBlock with a TextBox:



        <DataTemplate>
        <StackPanel>
        <TextBlock Text="whatever"
        MouseDown="TextBlock_MouseDown"
        Tag="{Binding ElementName=tb}" />
        <TextBox Name="tb" />
        </StackPanel>
        </DataTemplate>


        Note the use of {Binding ElementName=tb} on the Tag to refer to the TextBox named tb.



        And in your code-behind:



        private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
        {
        FrameworkElement textBlock = (FrameworkElement)sender;
        TextBox editBox = (TextBox)(textBlock.Tag);
        editBox.Text = "Wow!"; // or set visible or whatever
        }


        (To avoid the use of the nasty Tag property, you could define a custom attached property to carry the TextBox binding, but for brevity I'm not showing that.)






        share|improve this answer

























          up vote
          4
          down vote










          up vote
          4
          down vote









          The ideal way to do this would be to create a ClickEditableTextBlock control, which by default renders as a TextBlock but shows a TextBox when the user clicks it. Because any given ClickEditableTextBlock has only one TextBlock and one TextBox, you don't have the matching issue. Then you use a ClickEditableTextBlock instead of separate TextBlocks and TextBoxes in your DataTemplate.



          This has the side benefit of encapsulating the functionality in a control so you don't pollute your main window code-behind with the edit behaviour, plus you can easily reuse it in other templates.





          If this sounds like too much effort, you can use Tag or an attached property to associate each TextBlock with a TextBox:



          <DataTemplate>
          <StackPanel>
          <TextBlock Text="whatever"
          MouseDown="TextBlock_MouseDown"
          Tag="{Binding ElementName=tb}" />
          <TextBox Name="tb" />
          </StackPanel>
          </DataTemplate>


          Note the use of {Binding ElementName=tb} on the Tag to refer to the TextBox named tb.



          And in your code-behind:



          private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
          {
          FrameworkElement textBlock = (FrameworkElement)sender;
          TextBox editBox = (TextBox)(textBlock.Tag);
          editBox.Text = "Wow!"; // or set visible or whatever
          }


          (To avoid the use of the nasty Tag property, you could define a custom attached property to carry the TextBox binding, but for brevity I'm not showing that.)






          share|improve this answer














          The ideal way to do this would be to create a ClickEditableTextBlock control, which by default renders as a TextBlock but shows a TextBox when the user clicks it. Because any given ClickEditableTextBlock has only one TextBlock and one TextBox, you don't have the matching issue. Then you use a ClickEditableTextBlock instead of separate TextBlocks and TextBoxes in your DataTemplate.



          This has the side benefit of encapsulating the functionality in a control so you don't pollute your main window code-behind with the edit behaviour, plus you can easily reuse it in other templates.





          If this sounds like too much effort, you can use Tag or an attached property to associate each TextBlock with a TextBox:



          <DataTemplate>
          <StackPanel>
          <TextBlock Text="whatever"
          MouseDown="TextBlock_MouseDown"
          Tag="{Binding ElementName=tb}" />
          <TextBox Name="tb" />
          </StackPanel>
          </DataTemplate>


          Note the use of {Binding ElementName=tb} on the Tag to refer to the TextBox named tb.



          And in your code-behind:



          private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
          {
          FrameworkElement textBlock = (FrameworkElement)sender;
          TextBox editBox = (TextBox)(textBlock.Tag);
          editBox.Text = "Wow!"; // or set visible or whatever
          }


          (To avoid the use of the nasty Tag property, you could define a custom attached property to carry the TextBox binding, but for brevity I'm not showing that.)







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jan 18 '10 at 20:43

























          answered Jan 18 '10 at 20:35









          itowlson

          64.4k12137142




          64.4k12137142






















              up vote
              1
              down vote













              If I may supplement, in order to cover the (double) part of the original question, in Youngjae's reply you make the following replacement in the xaml file:



              <TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" MouseDown="textBlockName_MouseDown" />


              is replaced with



              <TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" >
              <TextBlock.InputBindings>
              <MouseBinding Gesture="LeftDoubleCLick" Command="{StaticResource cmdEditTextblock}"/>
              </TextBlock.InputBindings>
              </TextBlock>


              adding also the proper RoutedCommand in UserControl.Resources



              <UserControl.Resources>
              <RoutedCommand x:Key="cmdEditTextblock"/>
              </UserControl.Resources>


              and a CommandBinding in UserControl.CommandBindings



              <UserControl.CommandBindings>
              <CommandBinding Command="{StaticResource cmdEditTextblock}"
              Executed="CmdEditTextblock_Executed"/>
              </UserControl.CommandBindings>


              Also in the code behind file:



              private void textBlockName_MouseDown(object sender, MouseButtonEventArgs e)
              {
              var grid = ((Grid) ((TextBlock) sender).Parent);
              var tbx = (TextBox)grid.Children[1];
              ((TextBlock)sender).Visibility = Visibility.Collapsed;
              tbx.Visibility = Visibility.Visible;
              this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
              }


              is replaced by



              private void CmdEditTextblock_Executed(object sender, ExecutedRoutedEventArgs e)
              {
              var grid = ((Grid)((TextBlock)e.OriginalSource).Parent);
              var tbx = (TextBox)grid.Children[1];
              ((TextBlock)e.OriginalSource).Visibility = Visibility.Collapsed;
              tbx.Visibility = Visibility.Visible;
              this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
              }


              In case some people want to have left doubleclick as input gesture, like I did...






              share|improve this answer

























                up vote
                1
                down vote













                If I may supplement, in order to cover the (double) part of the original question, in Youngjae's reply you make the following replacement in the xaml file:



                <TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" MouseDown="textBlockName_MouseDown" />


                is replaced with



                <TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" >
                <TextBlock.InputBindings>
                <MouseBinding Gesture="LeftDoubleCLick" Command="{StaticResource cmdEditTextblock}"/>
                </TextBlock.InputBindings>
                </TextBlock>


                adding also the proper RoutedCommand in UserControl.Resources



                <UserControl.Resources>
                <RoutedCommand x:Key="cmdEditTextblock"/>
                </UserControl.Resources>


                and a CommandBinding in UserControl.CommandBindings



                <UserControl.CommandBindings>
                <CommandBinding Command="{StaticResource cmdEditTextblock}"
                Executed="CmdEditTextblock_Executed"/>
                </UserControl.CommandBindings>


                Also in the code behind file:



                private void textBlockName_MouseDown(object sender, MouseButtonEventArgs e)
                {
                var grid = ((Grid) ((TextBlock) sender).Parent);
                var tbx = (TextBox)grid.Children[1];
                ((TextBlock)sender).Visibility = Visibility.Collapsed;
                tbx.Visibility = Visibility.Visible;
                this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
                }


                is replaced by



                private void CmdEditTextblock_Executed(object sender, ExecutedRoutedEventArgs e)
                {
                var grid = ((Grid)((TextBlock)e.OriginalSource).Parent);
                var tbx = (TextBox)grid.Children[1];
                ((TextBlock)e.OriginalSource).Visibility = Visibility.Collapsed;
                tbx.Visibility = Visibility.Visible;
                this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
                }


                In case some people want to have left doubleclick as input gesture, like I did...






                share|improve this answer























                  up vote
                  1
                  down vote










                  up vote
                  1
                  down vote









                  If I may supplement, in order to cover the (double) part of the original question, in Youngjae's reply you make the following replacement in the xaml file:



                  <TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" MouseDown="textBlockName_MouseDown" />


                  is replaced with



                  <TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" >
                  <TextBlock.InputBindings>
                  <MouseBinding Gesture="LeftDoubleCLick" Command="{StaticResource cmdEditTextblock}"/>
                  </TextBlock.InputBindings>
                  </TextBlock>


                  adding also the proper RoutedCommand in UserControl.Resources



                  <UserControl.Resources>
                  <RoutedCommand x:Key="cmdEditTextblock"/>
                  </UserControl.Resources>


                  and a CommandBinding in UserControl.CommandBindings



                  <UserControl.CommandBindings>
                  <CommandBinding Command="{StaticResource cmdEditTextblock}"
                  Executed="CmdEditTextblock_Executed"/>
                  </UserControl.CommandBindings>


                  Also in the code behind file:



                  private void textBlockName_MouseDown(object sender, MouseButtonEventArgs e)
                  {
                  var grid = ((Grid) ((TextBlock) sender).Parent);
                  var tbx = (TextBox)grid.Children[1];
                  ((TextBlock)sender).Visibility = Visibility.Collapsed;
                  tbx.Visibility = Visibility.Visible;
                  this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
                  }


                  is replaced by



                  private void CmdEditTextblock_Executed(object sender, ExecutedRoutedEventArgs e)
                  {
                  var grid = ((Grid)((TextBlock)e.OriginalSource).Parent);
                  var tbx = (TextBox)grid.Children[1];
                  ((TextBlock)e.OriginalSource).Visibility = Visibility.Collapsed;
                  tbx.Visibility = Visibility.Visible;
                  this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
                  }


                  In case some people want to have left doubleclick as input gesture, like I did...






                  share|improve this answer












                  If I may supplement, in order to cover the (double) part of the original question, in Youngjae's reply you make the following replacement in the xaml file:



                  <TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" MouseDown="textBlockName_MouseDown" />


                  is replaced with



                  <TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" >
                  <TextBlock.InputBindings>
                  <MouseBinding Gesture="LeftDoubleCLick" Command="{StaticResource cmdEditTextblock}"/>
                  </TextBlock.InputBindings>
                  </TextBlock>


                  adding also the proper RoutedCommand in UserControl.Resources



                  <UserControl.Resources>
                  <RoutedCommand x:Key="cmdEditTextblock"/>
                  </UserControl.Resources>


                  and a CommandBinding in UserControl.CommandBindings



                  <UserControl.CommandBindings>
                  <CommandBinding Command="{StaticResource cmdEditTextblock}"
                  Executed="CmdEditTextblock_Executed"/>
                  </UserControl.CommandBindings>


                  Also in the code behind file:



                  private void textBlockName_MouseDown(object sender, MouseButtonEventArgs e)
                  {
                  var grid = ((Grid) ((TextBlock) sender).Parent);
                  var tbx = (TextBox)grid.Children[1];
                  ((TextBlock)sender).Visibility = Visibility.Collapsed;
                  tbx.Visibility = Visibility.Visible;
                  this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
                  }


                  is replaced by



                  private void CmdEditTextblock_Executed(object sender, ExecutedRoutedEventArgs e)
                  {
                  var grid = ((Grid)((TextBlock)e.OriginalSource).Parent);
                  var tbx = (TextBox)grid.Children[1];
                  ((TextBlock)e.OriginalSource).Visibility = Visibility.Collapsed;
                  tbx.Visibility = Visibility.Visible;
                  this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
                  }


                  In case some people want to have left doubleclick as input gesture, like I did...







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Sep 28 at 9:41









                  tombobadil

                  113




                  113






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f2088909%2finline-editing-textblock-in-a-listbox-with-data-template-wpf%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      這個網誌中的熱門文章

                      Xamarin.form Move up view when keyboard appear

                      Post-Redirect-Get with Spring WebFlux and Thymeleaf

                      Anylogic : not able to use stopDelay()