我正在尝试创建一个TreeView,它允许用户重命名TreeView中的节点。该树表示一条HL7消息,并按层次从段到子组件构建。
例如:
PID
PID.1
PID.2
etc...我需要允许用户选择一个节点,按F2将该节点置于编辑模式。因为HL7允许重复消息结构,所以我还需要SelectedItem,以便在存在重复名称的情况下知道更改了哪个节点。
目前,每个节点都是一个IsReadOnly设置为true的TextBox,并且样式化后看起来像一个TextBlock。当用户按下F2时,我设置了TextBox的样式,使其看起来像通常的输入一样。问题是,TextBox正在吞噬所有的鼠标事件,阻止TreeView设置SelectedItem或引发SelectedItemChanged。
我在MSDN上发现了一些讨论,其中有人建议在TextBox上使用PreviewMouseLeftButtonDown事件。我正在使用它,而TextBox仍然在使用该事件。
以前有没有人遇到过这个问题,或者有什么建议?
发布于 2011-07-06 05:32:41
另一种方法是有一个用于显示的TextBlock和一个用于编辑的隐藏TextBox。在TreeView上侦听F2,它将接收键盘事件,因为TextBox在隐藏时不会获得任何输入焦点。当按下F2时,隐藏TextBlock并显示TextBox以供编辑。处理TextBox上的LostFocus事件以隐藏TextBox并再次显示TextBlock。
这样做的一个好处是,你不必假冒一个看起来和行为都像TextBlock的TextBox。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;
}
}https://stackoverflow.com/questions/6586488
复制相似问题