访问内容模板中的控件的方法

时间:2012-01-12 15:32:24

标签: wpf binding datatemplate tabcontrol

相对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;
        }
    }
}

在我的MainWindow中,我有一个标签控件,它有一个项目模板(在每个标签的标题中显示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”标题,描述显示在正确的位置,按钮正确打开或关闭粗体。

我的问题是,如何添加选项卡控件的OUTSIDE按钮,该按钮可以调用MyControl对象的MyControl.ToggleBold方法,该方法位于所选项目的内容模板中:

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参数。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

您可以导航VisualTree以找到您正在寻找的控件。

例如,我使用一组custom VisualTreeHelpers来允许我这样调用:

var myControl = VisualTreeHelpers.FindChild<MyControl>(myTabControl);
if (myControl != null)
    myControl.ToggleBold();