2013-10-24 3 views
2

Это мой первый пост в stackoverlow, который я считаю лучшим сайтом онлайн-справки для C# и WPF.C# WPF Не удается получить доступ к кнопке, определенной в ControlTemplate из UserControl

Я исследовал около шести часов в течение последних трех дней, пытаясь выяснить, как прикрепить событие обработчика кнопок к кнопке, которую я определил в стиле. Моя ситуация, похоже, отличается от всех других примеров, которые я просмотрел в Интернете. Итак, здесь идет, и я, безусловно, ценю ваш вклад.

Отрывок из MainWindow.xaml где я определяю в сетке следующие

<ScrollViewer Grid.Column="2" Grid.ColumnSpan="2" 
     HorizontalScrollBarVisibility="Visible" 
     VerticalScrollBarVisibility="Hidden" 
     Background="AliceBlue"> 
    <ItemsControl ItemsSource="{Binding LaserDataItems}"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel Orientation="Horizontal" Background="AliceBlue" /> 
     </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
    </ItemsControl> 
    </ScrollViewer> 

Это связывание на LaserDataItems будет содержать список UserControls в display.These создаются динамически, по мере необходимости. Но я фактически пытаюсь выполнить всю свою работу в коде, находящемся за элементом управления (ниже)

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

<Style x:Key="HeaderStyle" TargetType="{x:Type DataGridColumnHeader}">    
    <Setter Property="Template"> 
    <Setter.Value> 
     <ControlTemplate TargetType="{x:Type DataGridColumnHeader}"> 
      <Button x:Name="MyButton" Height="20"/> 
     </ControlTemplate> 
    </Setter.Value> 
    </Setter> 
</Style> 

Вот является UserControl

<UserControl x:Class="EClient.Controls.GetAllLaserData" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <DataGrid Name="laserDataGrid" 
       ColumnHeaderStyle="{StaticResource HeaderStyle}" 
       AutoGenerateColumns="False" 
       ItemsSource="{Binding }" 
       IsReadOnly="True" 
       RowHeaderWidth="0" 
       Height="567" 
       VerticalAlignment="Top" 
       RowHeight="17"> 
     <DataGrid.Columns> 
      <DataGridTextColumn 
      Width="53" 
      Header="{Binding HeaderName}" 
      Binding="{Binding Name}"></DataGridTextColumn> 
     </DataGrid.Columns> 
     <DataGrid.RowStyle> 
      <Style TargetType="DataGridRow"> 
       <Setter Property="IsEnabled" Value="False"/> 
      </Style> 
     </DataGrid.RowStyle> 
    </DataGrid> 
</UserControl> 

В DataGrid этого UserControl является ColumnHeaderStyle, который присваивается шаблон: HeaderStyle , В этом стиле есть кнопка, которую мне нужно привязать обработчик клика, когда он создается. Как это сделать. Я попытался получить к нему доступ, переопределив метод OnApplyTemplate, но все, что я пытаюсь, возвращает null. Возможно ли, что кнопка еще не была создана при запуске этого метода? Должен быть способ добраться до этой кнопки.

Когда я запускаю это и успешно создаю список этих UserControls (которые являются datagrids), в первой ячейке можно увидеть кнопку (которая является заголовком каждой сетки).

Я также пробовал использовать общую процедуру, которая пересекает визуальное дерево, но безрезультатно. На самом деле это то, что я должен преследовать, я действительно в недоумении за идеи попробовать.


Следующий фрагмент был добавлен 10/26/2013

Хотя я нашел другое решение этой проблемы, я все еще заинтересован в его разрешении. Я действительно думал, что это довольно хороший вопрос.

В любом случае, я думал, что поместил бы фотографию того, что я пытался сделать. Возможно, это будет лучше рассматривать проблему.

Datagrid with Button Above Grid

+0

Эти ссылки могут помочь: http://stackoverflow.com/questions/4030764/how-to-get-datagridcolumnheader-from-datagridcolumn http://stackoverflow.com/questions/1658397/wpf-datagrid-header-text -связывание (не может). – Chris

+0

Chris, Эти ссылки действительно выглядят многообещающими. Спасибо. Когда я вернусь в город, я дам им попытку и дам вам знать. Спасибо, опять же - Rick – Rick

+0

Надеюсь, что-то полезное там, у меня была какая-то трещина, она не работала и наткнулась на них, пытаясь понять почему. – Chris

ответ

0

Не прямой ответ - но вот как я бы подойти к решению проблемы. Я не использую datagrids - вместо этого предпочитаю элементы управления, поэтому для примера я должен использовать элемент ItemsControl.

При обработке кнопок в списках я обычно разделяю элемент управления, содержащий кнопку, в свой собственный пользовательский элемент управления (применяя стиль по мере необходимости). Тогда у меня был бы обработчик событий в фоновом режиме, например.XAML

<UserControl x:Class="BindableTest.UserControls.CatItem" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="400"> 
    <StackPanel VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0 0 10 0"> 
    <Label Content="{Binding Path=Model.DisplayNumber}" HorizontalAlignment="Left" Height="25" Width="25" /> 
    <TextBox BorderBrush="Black" Text="{Binding Path=Model.SomeText, UpdateSourceTrigger=PropertyChanged}" Width="150" Height="25" /> 
    <StackPanel Orientation="Horizontal"> 
     <Button x:Name="btnDelete" Margin="5 0 0 0" Content="Delete" Click="btnDelete_Click_1"></Button> 
    </StackPanel> 
    </StackPanel> 
</UserControl> 

и код позади ...

/// <summary> 
    /// Interaction logic for CatItem.xaml 
    /// </summary> 
    public partial class CatItem : UserControl 
    { 
    public CatItem() 
    { 
     InitializeComponent();  
    } 

    private void btnDelete_Click_1(object sender, RoutedEventArgs e) 
    { 
     if (DeleteClick != null) 
     DeleteClick(sender, e); 
    } 

    public event RoutedEventHandler DeleteClick; 


    } 

От вызывающего XAML, вы можете использовать это событие, как показано ниже.

<ItemsControl x:Name="itmsList" ItemsSource="{Binding Path=ModelListVMs}"> 
    <ItemsControl.ItemsPanel> 
    <ItemsPanelTemplate> 
     <StackPanel Orientation="Horizontal"></StackPanel> 
    </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemTemplate> 
    <DataTemplate> 
     <uc:CatItem DeleteClick="ItemDeleteClick"></uc:CatItem> <!-- Using click here --> 
    </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

На заднем плане окна вы можете выбрать событие для любой кнопки.

public void ItemDeleteClick(object sender, RoutedEventArgs e) 
    { 
     var ctx = (sender as Button); 

     //can get datacontext and other properties easily from here 
    } 

Извините, но это не прямой ответ, но, надеюсь, он поможет вам в правильном направлении.

+1

HockeyJ, Большое спасибо за ваши отзывы. Хотя это не отвечает на мой вопрос, это дало мне идею переделать мой контроль. Я вытащил кнопку из шаблона Control и вместо этого поместил ее (кнопку) в панель Stack (с кнопкой над сеткой данных). Мне все еще любопытно, почему я не смог найти кнопку. Когда я рекурсивно прошел визуальное дерево сетки данных с использованием ссылки laserGataGrid, то, как я полагаю, я видел, было родословное определение Data-grid, а не мое настроенное. Так что продолжайте искать ответ, но я очень ценю ваши отзывы. – Rick

+0

@Rick: Если у вас есть дополнительная информация для добавления, добавьте ее в исходный вопрос, а не ответ. – Makoto

+0

Спасибо Макато. Я сделаю так. – Rick

Смежные вопросы