WPF TreeView SelectedItemChanged не стреляет - PullRequest
2 голосов
/ 05 июля 2011

Я пытаюсь создать TreeView, который позволяет пользователю переименовывать узлы в TreeView.Дерево представляет сообщение HL7 и структурировано из сегмента в субкомпонент иерархически.

Например:

PID
   PID.1
   PID.2
   etc...

Мне нужно разрешить пользователю выбирать узел, нажмите F2, чтобы поместить узелв режим редактирования.Поскольку HL7 позволяет повторять структуры сообщений, мне также нужен SelectedItem, чтобы я мог знать, какой узел был изменен в случае наличия повторяющихся имен.

В настоящее время каждый узел представляет собой TextBox с IsReadOnly, установленным в true, и стилизован так, чтобы выглядетьтекстовый блок.Когда пользователь нажимает клавишу F2, я стилизую TextBox, чтобы он выглядел так, как обычно для ввода.Проблема в том, что TextBox съедает все события мыши, не позволяя TreeView установить SelectedItem или вызвать SelectedItemChanged.

Я обнаружил некоторые обсуждения в MSDN, где один человек говорит, что использует событие PreviewMouseLeftButtonDown в TextBox.Я использую это, и TextBox все еще использует событие.

Кто-нибудь сталкивался с этим раньше или есть какие-либо предложения?

1 Ответ

0 голосов
/ 06 июля 2011

Другим способом является наличие 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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...