Silverlight: определение обработчика событий в шаблоне иерархических данных - PullRequest
3 голосов
/ 01 сентября 2009

У меня проблемы с получением события нажатия кнопки, и я использую Silverlight 3.0 с соответствующим Silverlight Toolkit .

Проблема

У меня есть это TreeView:

Пример TreeView http://a.imagehost.org/0939/TreeView.png.

Значение для определенного узла является суммой значений его дочерних элементов. Только в листьях могут быть добавлены данные (пока). Я хочу добиться того, чтобы пользователь мог добавлять (и в конечном итоге удалять) записи в дереве, чтобы в конечном итоге создать собственную диаграмму. Для этого я бы хотел, чтобы знак «плюс» вставлял новую строку / узел как дочерний элемент узла, на котором щелкнул пользователь. (То есть, если я нажимаю «плюс» в «Дисплее», я получаю строку ниже, чтобы указать CRT или TFT или что-либо еще.)

Дело в том, что, несмотря на все мои мозги, я не знаю, как получить какое-либо полезное событие. TextBlock, TextBox и Button определены в иерархическом шаблоне, и я не могу определить обработчик Click в этом шаблоне.

OTOH, я не нашел способа получить элементы шаблона определенного TreeViewItem из (c #) кода. Очень хорошо, я могу сделать trv.ItemContainerGenerator.GetContainerFromItem (item), и, как показал Джастин Ангел , я очень хорошо могу изменить размер шрифта, но не нашел никакого способа получить доступ к текстовому полю или кнопке.

Есть ли способ зафиксировать событие нажатия кнопки? Или какой-нибудь альтернативный способ получить что-то, что дает функциональность «добавить ниже»?

Заранее спасибо.


Больше данных

Дерево xaml выглядит так:

<controls:TreeView x:Name="SankeyDataTree" 
    ItemTemplate="{StaticResource SankeyTreeTemplate}" BorderThickness="0" 
    Background="{x:Null}" HorizontalAlignment="Left" VerticalAlignment="Top">
    <controls:TreeViewItem IsExpanded="True">
        <controls:TreeViewItem.HeaderTemplate>
            <DataTemplate>
                <TextBlock Text="Loading..."/>
            </DataTemplate>
        </controls:TreeViewItem.HeaderTemplate>
    </controls:TreeViewItem>
</controls:TreeView>

Я использую этот HierarchicalDataTemplate (и украл оценку у Тимми Кокке ):

<Data:HierarchicalDataTemplate x:Key="SankeyTreeTemplate" ItemsSource="{Binding Children}">
    <Grid Height="24">
        <Grid.ColumnDefinitions>
            <!-- ... -->
        </Grid.ColumnDefinitions>
        <TextBlock Text="{Binding Path=Value.name, Mode=TwoWay}" VerticalAlignment="Center"/>
        <TextBox Text="{Binding Path=Value.flow, Mode=TwoWay}" Margin="4,0" VerticalAlignment="Center" d:LayoutOverrides="Width" Grid.Column="1" TextAlignment="Right" Visibility="{Binding Children, Converter={StaticResource BoxConverter}, ConverterParameter=\{box\}}"/>
        <TextBlock Text="{Binding Path=Value.throughput, Mode=TwoWay}" Margin="4,0" VerticalAlignment="Center" d:LayoutOverrides="Width" Grid.Column="1" TextAlignment="Right" Visibility="{Binding Children, Converter={StaticResource BoxConverter}, ConverterParameter=\{block\}}"/>
        <Button Margin="0" Grid.Column="2" Style="{StaticResource TreeViewItemButtonStyle}">
            <Image Source="../Assets/add.png" Margin="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Button>
    </Grid>
</Data:HierarchicalDataTemplate>

К этому TreeView привязано « SimpleTree », значения которого в основном содержат только строку (имя) и два типа double (поток и пропускная способность).

public String name { get; set; }
public Double flow { get; set; }
public Double throughput { get; set; }

(плюс код для INotifyPropertyChanged, чтобы получить двухстороннюю привязку к текстовым полям.)

Ответы [ 2 ]

3 голосов
/ 01 сентября 2009

Вы можете присоединить Behavior к Button в HierarchicalDataTemplate и позволить этому обрабатывать Click события из Button.

Загрузите и установите Expression Blend 3 SDK . Добавьте ссылку на System.Windows.Interactivity в проект и добавьте Behavior, прикрепленный к Button:

public class ButtonClickBehavior : Behavior<Button> {

  protected override void OnAttached() {
    base.OnAttached();
    AssociatedObject.Click += ButtonClick;
  }

  protected override void OnDetaching() {
    base.OnDetaching();
    AssociatedObject.Click -= ButtonClick;
  }

  void ButtonClick(object sender, RoutedEventArgs e) {
    Node node = AssociatedObject.DataContext as Node;
    if (node != null) {
      // Button clicked. Do something to associated node.
    }
  }

}

Присоедините Behavior к Button в HierarchicalDataTemplate (при условии, что это объявление пространства имен: xmlns:interactivity="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"):

<Button Margin="0" Grid.Column="2" Style="{StaticResource TreeViewItemButtonStyle}">
  <Image Source="../Assets/add.png" Margin="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
  <interactivity:Interaction.Behaviors>
    <local:ButtonClickBehavior/>
  </interactivity:Interaction.Behaviors>
</Button>

При желании вы можете добавить свойства к ButtonClickBehavior и установить их из XAML для создания более многократно используемого Behavior.

3 голосов
/ 01 сентября 2009

Вы можете обработать событие нажатия кнопки в коде позади. Чтобы получить данные, просто привяжите их к атрибуту Tag.

<Button Margin="0" Grid.Column="2" 
        Click="Button_Click" Tag="{Binding}"
        Style="{StaticResource     TreeViewItemButtonStyle}">            
  <Image Source="../Assets/add.png" Margin="0" 
         HorizontalAlignment="Center" VerticalAlignment="Center"/>        
</Button>

В коде позади, обработайте его и получите доступ к элементу.

private void Button_Click(object sender, RoutedEventArgs e)
{
   var data = ((Button)sender).Tag as SimpleTreeNode
}

Где SimpleTreeNode - имя класса вашего элемента дерева.

Вы сможете добавить новый узел к найденным данным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...