Относительный новичок в WPF, возможно, это будет простое решение (надеюсь!). У меня есть класс с двумя свойствами:
public class MyClass
{
public String Name { get; set; }
public String Description { get; set; }
}
У меня есть пользовательский элемент управления, в котором есть текстовый блок и кнопка: текстовый блок отображает текст (очевидно), а кнопка используется либо для полужирного, либо для полужирного текста текстового блока:
MyControl.xaml:
<UserControl
x:Class="WpfApplication1.MyControl"
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"
xmlns:this="clr-namespace:WpfApplication1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="48" />
</Grid.ColumnDefinitions>
<TextBlock
x:Name="txtDescription"
Grid.Column="0"
Text="{Binding Path=Description, RelativeSource={RelativeSource AncestorType={x:Type this:MyControl}}}" />
<Button
x:Name="btnBold"
Grid.Column="1"
Content="Bold"
Click="btnBold_Click" />
</Grid>
</UserControl>
MyControl.xaml.cs:
public partial class MyControl : UserControl
{
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register("Description", typeof(String), typeof(MyControl));
public String Description
{
get { return GetValue(MyControl.DescriptionProperty) as String; }
set { SetValue(MyControl.DescriptionProperty, value); }
}
public MyControl()
{
InitializeComponent();
}
private void btnBold_Click(object sender, RoutedEventArgs e)
{
ToggleBold();
}
public void ToggleBold()
{
if (txtDescription.FontWeight == FontWeights.Bold)
{
btnBold.Content = "Bold";
txtDescription.FontWeight = FontWeights.Normal;
}
else
{
btnBold.Content = "Unbold";
txtDescription.FontWeight = FontWeights.Bold;
}
}
}
В моем главном окне у меня есть элемент управления вкладкой, который имеет шаблон элемента (для отображения MyClass.Name в заголовке каждой вкладки) и шаблон содержимого. Шаблон содержимого содержит один из указанных выше элементов управления, и MyClass.Description привязано к MyControl.Description:
MainWindow.xaml:
<Window
x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350"
Width="525"
xmlns:this="clr-namespace:WpfApplication1">
<Grid>
<TabControl x:Name="tabItems">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<this:MyControl
Description="{Binding Description}" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
</Window>
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<MyClass> myClasses = new List<MyClass>();
myClasses.Add(new MyClass() { Name = "My Name", Description = "My Description" });
myClasses.Add(new MyClass() { Name = "Your Name", Description = "Your Description" });
tabItems.ItemsSource = myClasses;
}
}
Когда программа запускается, я добавляю два объекта типа MyClass в список List, присваиваю список свойству ItemsSource элемента управления вкладками, и все работает отлично: я получаю две вкладки с «My Name» и «Your Name» как заголовки, описание отображается в правильном месте, а кнопка включает или выключает жирный шрифт правильно.
Мой вопрос заключается в следующем: как добавить кнопку ВНЕ элемента управления вкладками, которая могла бы вызвать метод MyControl.ToggleBold объекта MyControl, который находится в шаблоне содержимого выбранного элемента:
MainWindow.xaml:
<Window
x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350"
Width="525"
xmlns:this="clr-namespace:WpfApplication1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TabControl x:Name="tabItems" Grid.Row="0">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<this:MyControl
x:Name="myControl"
Description="{Binding Description}"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
<Button Grid.Row="1" Content="Toggle Selected Tab" Click="Button_Click" />
</Grid>
</Window>
MainWindow.xaml.cs:
...
private void Button_Click(object sender, RoutedEventArgs e)
{
MyClass myClass = tabItems.SelectedItem as MyClass;
MyControl myControl;
///get the instance of myControl that is contained
///in the content template of tabItems for the
///myClass item
myControl.ToggleBold();
}
...
Я знаю, что могу получить доступ к шаблону данных, вызвав tabItems.SelectedContentTemplate, но, насколько я могу судить, я не могу получить доступ к элементам управления в шаблоне (и я не думаю, что мне следует это делать). Существует метод FindName, но я не знаю, передать как параметр templatedParent.
Любая помощь будет принята с благодарностью.