Другим способом является наличие TextBlock для отображения и скрытого TextBox для редактирования. Прослушайте F2 в TreeView, который будет получать события клавиатуры, поскольку TextBox не будет фокусироваться, пока он скрыт. Когда F2 нажата, скрыть TextBlock и показать TextBox для редактирования. Обработайте событие LostFocus в TextBox, чтобы скрыть TextBox и снова отобразить TextBlock.
Одним из преимуществ такого способа является то, что вам не нужно подделывать TextBox, чтобы выглядеть и вести себя как TextBlock. TextBlock всегда будет выглядеть и вести себя как TextBlock, а TextBox всегда будет выглядеть и вести себя как TextBox, и каждый из них сможет наследовать любой стиль, примененный на более высоком уровне ресурсов.
Редактировать: добавление примера кода.
Вот XAML:
<Window.Resources>
<Style x:Key="TreeViewTextBlockStyle" TargetType="TextBlock">
<Setter Property="Text" Value="{Binding DisplayText}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding InEditMode}" Value="true">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="TreeViewTextBoxStyle" TargetType="TextBox">
<Setter Property="Text" Value="{Binding DisplayText, Mode=TwoWay}"/>
<Setter Property="MinWidth" Value="50"/>
<EventSetter Event="LostFocus" Handler="TreeViewTextBox_LostFocus" />
<Style.Triggers>
<DataTrigger Binding="{Binding InEditMode}" Value="false">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="{Binding InEditMode}" Value="true">
<Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Mode=Self}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
<HierarchicalDataTemplate x:Key="HL7MessageTemplate" ItemsSource="{Binding Segments}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="[msg]--" FontWeight="Bold"/>
<TextBlock Style="{StaticResource TreeViewTextBlockStyle}"/>
<TextBox Style="{StaticResource TreeViewTextBoxStyle}" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate x:Key="HL7SegmentTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="[seg]--" FontWeight="Bold"/>
<TextBlock Style="{StaticResource TreeViewTextBlockStyle}"/>
<TextBox Style="{StaticResource TreeViewTextBoxStyle}" />
</StackPanel>
</DataTemplate>
<HierarchicalDataTemplate x:Key="HL7SegmentWithSubcomponentsTemplate" ItemsSource="{Binding Subcomponents}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="[seg+sub]--" FontWeight="Bold"/>
<TextBlock Style="{StaticResource TreeViewTextBlockStyle}"/>
<TextBox Style="{StaticResource TreeViewTextBoxStyle}" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate x:Key="HL7SubcomponentTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="[sub]--" FontWeight="Bold"/>
<TextBlock Style="{StaticResource TreeViewTextBlockStyle}"/>
<TextBox Style="{StaticResource TreeViewTextBoxStyle}" />
</StackPanel>
</DataTemplate>
<local:HL7DataTemplateSelector x:Key="HL7DataTemplateSelector"/>
</Window.Resources>
<Grid>
<TreeView Name="treeView1" ItemsSource="{Binding}" ItemTemplateSelector="{StaticResource HL7DataTemplateSelector}" KeyUp="treeView1_KeyUp"/>
</Grid>
Вот код:
private void treeView1_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.F2)
{
HL7Object selectedHL7Object = treeView1.SelectedItem as HL7Object;
if (selectedHL7Object != null)
{
selectedHL7Object.InEditMode = true;
}
}
}
private void TreeViewTextBox_LostFocus(object sender, RoutedEventArgs e)
{
HL7Object selectedHL7Object = treeView1.SelectedItem as HL7Object;
if (selectedHL7Object != null)
{
selectedHL7Object.InEditMode = false;
}
}
В этом коде предполагается, что ваш HL7Object является базовым классом для ваших объектов данных, например:
public class HL7Object : INotifyPropertyChanged
{
private string DisplayTextField;
public string DisplayText
{
get { return this.DisplayTextField; }
set
{
if (this.DisplayTextField != value)
{
this.DisplayTextField = value;
this.OnPropertyChanged("DisplayText");
}
}
}
private bool InEditModeField = false;
public bool InEditMode
{
get { return this.InEditModeField; }
set
{
if (this.InEditModeField != value)
{
this.InEditModeField = value;
this.OnPropertyChanged("InEditMode");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
А также, что вы реализовали DataTemplateSelector, который, как я полагаю, у вас есть из-за ваших сложных требований. Если нет, вот пример:
public class HL7DataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
FrameworkElement element = container as FrameworkElement;
if (element != null && item != null &&
(item is HL7Message || item is HL7Segment || item is HL7Subcomponent)
)
{
HL7Message message = item as HL7Message;
if (message != null)
{
return element.FindResource("HL7MessageTemplate") as DataTemplate;
}
HL7Segment segment = item as HL7Segment;
if (segment != null)
{
if (segment.Subcomponents != null && segment.Subcomponents.Count > 0)
{
return element.FindResource("HL7SegmentWithSubcomponentsTemplate") as DataTemplate;
}
else
{
return element.FindResource("HL7SegmentTemplate") as DataTemplate;
}
}
HL7Subcomponent subcomponent = item as HL7Subcomponent;
if (subcomponent != null)
{
return element.FindResource("HL7SubcomponentTemplate") as DataTemplate;
}
}
return null;
}
}