|
|
Comments and Discussions
|
|
 |

|
Simply change the EditableTextBlock.cs namespace from Borgstrup.DocBase.Client.Controls to Borgstrup.EditableTextBlock.
See ya !
|
|
|
|

|
Helpful solution but not 100% perfect.
|
|
|
|

|
Namespace for EditableTextBlock.xaml has to be changed into Borgstrup.EditableTextBlock.
|
|
|
|

|
I have a treeview populated by custom elements (CDir and CFile) are showed correctly (the label text i mean) and when i press on F2 the event on tree is ok and I arrive to set the property EditMode to true.
But the events lied to TextBox (TextBox_KeyDown, TextBox_Loaded, TextBox_LostFocus) doesn't trigger...I don't know to solve it
This is my code xaml:
<Grid>
<Grid.Resources></Grid.Resources>
<TreeView Name="m_treeView" KeyDown="m_treeView_KeyDown" SelectedItemChanged="m_treeView_SelectedItemChanged">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=ListElements}">
<StackPanel Orientation="Horizontal" Margin="2" Background="Transparent">
<Image Margin="2" Source="{Binding Converter={StaticResource CustomImageConverter}}"/>
<local:EditableTextBlock Text="{Binding Path=LabelName}" Margin="2"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
It seems that the <Style.Triggers> doesn't switch... Do you have an idea??
P.s.Your example is Ok on VS2008 and VS2010.
|
|
|
|

|
Hi there!
This control works great but I could not get it to work with the F2 key to begin editing. I tried to handle KeyDown and PreviewKeyDown but they don't seem to be routed to the control. Any help please?
Thank you very much!!!
Best regards
Mello
|
|
|
|
|

|
The sample code does not work
|
|
|
|

|
I would have voted 5 because this little demo solves exactly my problem, but
- you need to manually change the namespace of "EditableTextBlock.xaml.cs" to Borgstrup.EditableTextBlock before the project compiles
- the usual "slow double click" to begin editing is not implemented
- and the usage in a databound context could be better (documented)
Nevertheless is saved me time and therefore I vote 4
Christian
---
Always expect the unexpected!
|
|
|
|

|
Christian,
It sounds like you were able to fix the problems. Do you have any code that you can post?
Beth
|
|
|
|

|
Hi, I need to edit the TextBlock in multiline mode, eg. if I push CTRL+ENTER the cursor goes on another line, ENTER confirms editing and exits. Is it possible ?
|
|
|
|
|

|
Suppose i got the following code to define the tree view nodes:
<TreeView Name="FoldersTree" Width="200" DockPanel.Dock="Left" HorizontalAlignment="Left"
KeyDown="FoldersTree_KeyDown">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Items}">
<StackPanel Orientation="Horizontal" >
<Image Source="{Binding Path=Icon}" />
<TextBlock xml:space="preserve"> </TextBlock>
<local:EditableTextBlock Text="{Binding Path=Name}" ToolTip="{Binding Path=Name}"/>
</StackPanel >
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
How can i get the EditableTextBlock in the FoldersTree_KeyDown() function in order to set the IsInEditMode = true property?
When i do FodlersTree.SelectedItem i am not getting TreeViewItem, but rather my data bound objects...
|
|
|
|

|
I got the same problem? Did anyone find a solution for this?
|
|
|
|

|
Hi, I have the same problem too. How do I get the item if using the tree with HierachicalDataTemplate?
Is there any hint to resolve this?
|
|
|
|

|
On event KeyDown
private void m_treeView_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.F2)
{
EditableTextBlock etb = null;
DataTemplate dt = m_treeView.ItemTemplate;
StackPanel sp = dt.LoadContent() as StackPanel; --> To test null....
UIElementCollection cool = sp.Children;
for (int i = 0; i < cool.Count; i++)
{
object o = cool[i];
if (o as EditableTextBlock != null)
{ etb = o as EditableTextBlock; break; }
}
if (etb != null)
{
if (etb.IsEditable)
{
etb.EditMode = true
}
}
}
}
|
|
|
|

|
This doesn't work for me. The "DataTemplate dt = m_treeView.ItemTemplate" line just returns an empty representation of the item template. Consequently, the next line (StackPanel sp = dt.LoadContent() as StackPanel) returns null.
So, how can I access the EditableTextBlock control for the selected item in the TreeView so I can set the IsInEditMode variable?
Thanks.
|
|
|
|

|
Try this:
if (e.Key == Key.F2)
{
EditableTextBlock etb = null;
TreeViewItem tvi = m_treeView.SelectedItem as TreeViewItem;
DataTemplate dt = tvi.HeaderTemplate;
StackPanel sp = dt.LoadContent() as StackPanel;
UIElementCollection cool = sp.Children;
for (int i = 0; i < cool.Count; i++)
{
object o = cool[i];
if (o as EditableTextBlock != null)
{ etb = o as EditableTextBlock; break; }
}
if (etb != null)
{
if (etb.IsEditable)
{
etb.IsInEditMode = true;
}
}
}
|
|
|
|

|
<TreeView TreeViewItem.Selected="OnItemSelected" ... />
...
<local:EditableTextBlock Name="myEditableTextBlock" ... />
private void treeView1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.F2)
{
TreeViewItem tvi = tree.Tag as TreeViewItem;
EditableTextBlock etb = getEditableTextBlock(tvi);
if (etb != null)
{
if (etb.IsEditable)
{
etb.IsInEditMode = true;
}
}
}
}
private childItem FindVisualChild<childItem>(DependencyObject obj)
where childItem : DependencyObject
{
for (int i = 0; i < System.Windows.Media.VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = System.Windows.Media.VisualTreeHelper.GetChild(obj, i);
if (child != null && child is childItem)
return (childItem)child;
else
{
childItem childOfChild = FindVisualChild<childItem>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
protected EditableTextBlock getEditableTextBlock(TreeViewItem selectedTVI)
{
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(selectedTVI);
if (myContentPresenter == null)
return null;
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
EditableTextBlock editBox = myDataTemplate.FindName("myEditableTextBlock", myContentPresenter) as EditableTextBlock;
return editBox;
}
private void OnItemSelected(object sender, RoutedEventArgs e)
{
tree.Tag = e.OriginalSource;
}
modified 22 Jun '12 - 18:29.
|
|
|
|

|
Oh, it works! thanks a lot~
very hard work with the visual controls... so, any other easier solution?
|
|
|
|

|
Hi,
I was wondering if anyone has had success binding the IsInEditMode property?
I am using TwoWay binding and IsInEditMode seems to be getting updated when I change my bound member (which uses INotifyPropertyChanged) but the EditableTextBlock does not become editable, though the IsInEditMode dependency shows true.
Any help would be awesome.
Thanks,
Patrick
|
|
|
|

|
Patrick,
I was wondering if you ever figured it out? I am using the control too and I would like to trigger the Edit Mode programmatically via the the ViewModel. But, like you, just setting it is not enough.
Looking at the code, yes, it seems that it is not designed to work that way. Only user events (mouse, keyboard) currently trigger the switch between Edit and Display mode.
If I find a clean way, I'll let you know.
Regards,
Eric.
|
|
|
|

|
it's a cool one...
Regards,
- Kunal Chowdhury ( My Blog)
|
|
|
|

|
My application creates a hierarchical ObservableCollection<object> which is bound to my TreeView. The TreeViewItems are styled and arranged as follows:
<HierarchicalDataTemplate DataType="{x:Type Folder}"
ItemsSource="{Binding Path=Items}">
<uc:EditableTextBlock Text="{Binding Path=Name}" FontSize="12" Foreground="Blue"/>
</HierarchicalDataTemplate>
What works:
- Display TreeViewItems
- Drag and Drop TreeViewItems
- Edit TreeViewItems
- Modify my ObservableCollection and TreeViewItems reflect the change automatically.
What isn't working:
- After Editing a TreeViewItem, the change is not propagated up to the ObservableCollection.
- At this point, if the Collection is modified, it skips the TreeViewItem that was modified.
Its like the binding was lost when the TreeViewItem was edited which would explain both problems. Could this be what is happening?
Any thoughts on what might be the problem and/or solution?
Thanks,
|
|
|
|
|

|
Hello,
When I look at your code I saw some .NET Property wrappers for your Dependency Properties.
In some of them you do more than the simple GetValue/SetValue. This is clearly not recommended.
From MSDN: In all but exceptional circumstances, your wrapper implementations should perform only the GetValue and SetValue actions, respectively.
see http://msdn.microsoft.com/en-us/library/ms753358.aspx[^]
Beside of this nice work.
|
|
|
|

|
Great article!
I wanted something that worked like the older TreeView where you could click the TreeViewItem to edit it. I made the following modifications to implement that functionality.
In file EditableTextBlock.xaml.cs, rename 'namespace' (so the original code compiles).
from
'Borgstrup.DocBase.Client.Controls'
to
'Borgstrup.EditableTextBlock'
In file Window1.xaml.cs add the following 'using' statement.
using System.Windows.Threading;
Also in file Window1.xaml.cs add the following code.
private TreeViewItem tviToEdit;
private DispatcherTimer waitToEditDispatcherTimer;
private void treeView1_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
Point position = e.GetPosition(this.treeView1);
IInputElement inputElement = this.treeView1.InputHitTest(position);
if(inputElement is TextBlock) {
TextBlock tb = inputElement as TextBlock;
DependencyObject depObj = (DependencyObject)tb;
while((depObj != null) && !(depObj is TreeViewItem)) {
depObj = VisualTreeHelper.GetParent(depObj);
}
if((depObj != null) && (depObj is TreeViewItem)) {
TreeViewItem tvi = depObj as TreeViewItem;
if(tvi.IsSelected) {
if(this.waitToEditDispatcherTimer == null) {
this.waitToEditDispatcherTimer = new System.Windows.Threading.DispatcherTimer();
this.waitToEditDispatcherTimer.Tick += new EventHandler(this.waitToEditDispatcherTimer_Trigger);
this.waitToEditDispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 500);
}
this.tviToEdit = tvi;
this.waitToEditDispatcherTimer.Stop();
this.waitToEditDispatcherTimer.Start();
}
}
}
}
private void waitToEditDispatcherTimer_Trigger(object sender, EventArgs e) {
this.waitToEditDispatcherTimer.Stop();
if(treeView1.SelectedItem is TreeViewItem) {
TreeViewItem tvi = treeView1.SelectedItem as TreeViewItem;
if(tvi == this.tviToEdit)
SetCurrentItemInEditMode(true);
}
this.tviToEdit = null;
}
In file EditableTextBlock.xaml.cs, replace the 'TreeView' line with the following line.
<TreeView Margin="0" Name="treeView1" KeyDown="treeView1_KeyDown" PreviewMouseLeftButtonDown="treeView1_PreviewMouseLeftButtonDown">
You should probably add code to stop the timer if the TreeView control loses focus. This modification hasn't been extensively tested. However, it's a start.
|
|
|
|

|
That would definately work, sadly I found your comment after I implemented the feature!
Here's how I did it:
Hook onto the PreviewMouseDown event in the xaml:
<DataTemplate x:Key="DisplayModeTemplate">
<TextBlock PreviewMouseDown="TextBlock_MouseDown" Text="{Binding ElementName=mainControl, Path=Text, Mode=TwoWay}" Margin="0" />
</DataTemplate>
Then in the EditableTextBlock class, I added a few things:
Two dependency properties to allow the user to specify timing for the click to edit:
public double MinimumClickTime
{
get { return (double)GetValue(MinimumClickTimeProperty); }
set { SetValue(MinimumClickTimeProperty, value); }
}
public double MaximumClickTime
{
get { return (double)GetValue(MaximumClickTimeProperty); }
set { SetValue(MaximumClickTimeProperty, value); }
}
public static readonly DependencyProperty MaximumClickTimeProperty =
DependencyProperty.Register("MaximumClickTime", typeof(double), typeof(EditableTextBlock), new UIPropertyMetadata(700d));
public static readonly DependencyProperty MinimumClickTimeProperty =
DependencyProperty.Register("MinimumClickTime", typeof(double), typeof(EditableTextBlock), new UIPropertyMetadata(300d));
A DateTime to hold the last time the TextBlock was clicked:
DateTime _lastClicked;
Finally an event handler for PreviewMouseDown:
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
double timeBetweenClicks = (DateTime.Now - _lastClicked).TotalMilliseconds;
_lastClicked = DateTime.Now;
if (timeBetweenClicks > MinimumClickTime && timeBetweenClicks < MaximumClickTime)
{
IsInEditMode = true;
}
e.Handled = false;
}
|
|
|
|

|
Tried to use this in a data bound TreeView.
I had to change the namespace of the .cs file to Borgstrup.EditableTextBlock
Then it took me ages to figure out I had to set the Binding Mode=TwoWay
But now it works great!
Thank you.
|
|
|
|

|
Hi Jesper,
I have downloaded the code in this article and replaced EditableTextBlock.xaml.cs as mentioned in this article but i am not able to run the application. i am getting errors saying "EditableTextBlock does not conatin definition for IsEditable". Can you please send me the latest source code.
Regards,
Sushma
|
|
|
|

|
Replace the namespace in EditableTextBlock.xaml.cs to Borgstrup.EditableTextBlock
|
|
|
|

|
Your Dec 10 submission seems to have errors during build. Appears that you changed the namespace for the control.
Rod Cullison
J. Ollman & Associates
|
|
|
|

|
<style targettype="{x:Type TreeViewItem}">
</style>
Items get added but the text is always blank if I change the Datatemplate to be:
the text is just fine
|
|
|
|

|
i discovered this glitch a minute ago, too bad CP wont let me modify anymore...
the problem was that I mistakenly initialized the dependency properties in the constructor instead of using PropertyMetaData. Until I can do it, please replace the contents of the EditableTextBlock.xaml.cs with the following:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace Borgstrup.DocBase.Client.Controls
{
public partial class EditableTextBlock : UserControl
{
#region Constructor
public EditableTextBlock()
{
InitializeComponent();
base.Focusable = true;
base.FocusVisualStyle = null;
}
#endregion Constructor
#region Member Variables
private string oldText;
#endregion Member Variables
#region Properties
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
"Text",
typeof(string),
typeof(EditableTextBlock),
new PropertyMetadata(""));
public bool IsEditable
{
get { return (bool)GetValue(IsEditableProperty); }
set { SetValue(IsEditableProperty, value); }
}
public static readonly DependencyProperty IsEditableProperty =
DependencyProperty.Register(
"IsEditable",
typeof(bool),
typeof(EditableTextBlock),
new PropertyMetadata(true));
public bool IsInEditMode
{
get
{
if (IsEditable)
return (bool)GetValue(IsInEditModeProperty);
else
return false;
}
set
{
if (IsEditable)
{
if (value) oldText = Text;
SetValue(IsInEditModeProperty, value);
}
}
}
public static readonly DependencyProperty IsInEditModeProperty =
DependencyProperty.Register(
"IsInEditMode",
typeof(bool),
typeof(EditableTextBlock),
new PropertyMetadata(false));
public string TextFormat
{
get { return (string)GetValue(TextFormatProperty); }
set
{
if (value == "") value = "{0}";
SetValue(TextFormatProperty, value);
}
}
public static readonly DependencyProperty TextFormatProperty =
DependencyProperty.Register(
"TextFormat",
typeof(string),
typeof(EditableTextBlock),
new PropertyMetadata("{0}"));
public string FormattedText
{
get { return String.Format(TextFormat, Text); }
}
#endregion Properties
#region Event Handlers
void TextBox_Loaded(object sender, RoutedEventArgs e)
{
TextBox txt = sender as TextBox;
txt.Focus();
txt.SelectAll();
}
void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
this.IsInEditMode = false;
}
void TextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
this.IsInEditMode = false;
e.Handled = true;
}
else if (e.Key == Key.Escape)
{
this.IsInEditMode = false;
Text = oldText;
e.Handled = true;
}
}
#endregion Event Handlers
}
}
Yours Sincerely,
Jesper Borgstrup
|
|
|
|

|
Fantastic control - many thanks, and for the bug fix.
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
An editable TextBlock component that allows for in-place editing of, e.g., items in a TreeView.
| Type | Article |
| Licence | CPOL |
| First Posted | 8 Dec 2008 |
| Views | 63,021 |
| Downloads | 3,197 |
| Bookmarked | 41 times |
|
|