我正在尝试创建一个TreeView,它允许用户重命名TreeView中的节点。树表示HL7消息,并且从分段到子组件分层结构。
例如:
PID
PID.1
PID.2
etc...
我需要允许用户选择节点,按F2键将节点置于编辑模式。因为HL7允许重复消息结构,所以我还需要SelectedItem,这样我就知道在存在重复名称的情况下哪个节点被更改了。
目前,每个节点都是一个TextBox,其IsReadOnly设置为true,并被设计为看起来像TextBlock。当用户按下F2时,我将TextBox设置为看起来像通常用于输入的样式。问题是,TextBox正在吃掉所有鼠标事件,阻止TreeView设置SelectedItem或者提升SelectedItemChanged。
我在MSDN上找到了一些讨论,其中一个人说在TextBox上使用PreviewMouseLeftButtonDown事件。我正在使用它,TextBox仍在使用该事件。
有没有人遇到此问题或有任何建议?
答案 0 :(得分:0)
另一种方法是使用TextBlock进行显示,使用隐藏的TextBox进行编辑。在TreeView上收听F2,它将接收键盘事件,因为TextBox在隐藏时不会获得任何输入焦点。按下F2时,隐藏TextBlock并显示TextBox以进行编辑。处理TextBox上的LostFocus事件以隐藏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;
}
}