Inline editing TextBlock in a ListBox with Data Template (WPF)
up vote
9
down vote
favorite
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
add a comment |
up vote
9
down vote
favorite
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
As a tip, rather than usingpre
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
add a comment |
up vote
9
down vote
favorite
up vote
9
down vote
favorite
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
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
c# wpf xaml listbox datatemplate
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 usingpre
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
add a comment |
As a tip, rather than usingpre
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
add a comment |
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.
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
add a comment |
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.
Thanks for this solution, I use it viaDataTemplate
for myListBox
, but the new value does not get updated in the source. TheItemsSource
is of typeObservableCollection<string>
. Any ideas?
– Nicolas
Nov 8 at 12:10
add a comment |
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.)
add a comment |
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...
add a comment |
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.
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
add a comment |
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.
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
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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.
Thanks for this solution, I use it viaDataTemplate
for myListBox
, but the new value does not get updated in the source. TheItemsSource
is of typeObservableCollection<string>
. Any ideas?
– Nicolas
Nov 8 at 12:10
add a comment |
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.
Thanks for this solution, I use it viaDataTemplate
for myListBox
, but the new value does not get updated in the source. TheItemsSource
is of typeObservableCollection<string>
. Any ideas?
– Nicolas
Nov 8 at 12:10
add a comment |
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.
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.
edited Nov 8 at 9:26
community wiki
4 revs, 4 users 84%
Youngjae
Thanks for this solution, I use it viaDataTemplate
for myListBox
, but the new value does not get updated in the source. TheItemsSource
is of typeObservableCollection<string>
. Any ideas?
– Nicolas
Nov 8 at 12:10
add a comment |
Thanks for this solution, I use it viaDataTemplate
for myListBox
, but the new value does not get updated in the source. TheItemsSource
is of typeObservableCollection<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
add a comment |
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.)
add a comment |
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.)
add a comment |
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.)
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.)
edited Jan 18 '10 at 20:43
answered Jan 18 '10 at 20:35
itowlson
64.4k12137142
64.4k12137142
add a comment |
add a comment |
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...
add a comment |
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...
add a comment |
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...
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...
answered Sep 28 at 9:41
tombobadil
113
113
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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