wpf 在 Itemscontrol 数据模板中使用 FindAncestor 来查找数据模板之外的文本块

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13496495/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 06:19:18  来源:igfitidea点击:

Using FindAncestor from within an Itemscontrol datatemplate to find a textblock outside of the datatemplate

wpfrelativesourcefindancestor

提问by Dayman

I have a ItemsControl that's bound to an object, within the datatemplate of the ItemsControl i have two textblocks, I want to bind the first textblock's text property to another textblock that sits outside this ItemsControl.

我有一个绑定到对象的 ItemsControl,在 ItemsControl 的数据模板中,我有两个文本块,我想将第一个文本块的文本属性绑定到位于此 ItemsControl 之外的另一个文本块。

I have tried finding the object in the parent datacontext and also simply trying to find the TextBlock with the Path=Text

我尝试在父数据上下文中找到对象,也只是尝试使用 Path=Text 找到 TextBlock

one example is below :

一个例子如下:

 <TextBlock Name="Name" Text="{Binding Name}"                                                            
     Grid.Column="0"   
     FontSize="{DynamicResource SmallSize}"
     TextWrapping="Wrap"
     TextAlignment="Right"
     Padding="4,0,0,0"
     Grid.ColumnSpan="2" Background="Aqua"/>

     <ItemsControl ItemsSource="{Binding TheValue}"                                                  
         Padding="4,0,0,0" 
         Grid.Column="2"  
         HorizontalAlignment="Right">

         <ItemsControl.ItemTemplate>
             <DataTemplate>
                 <WrapPanel>
                     <TextBlock Text = "{
                           Binding RelativeSource = 
                               {RelativeSource FindAncestor, 
                                AncestorType={x:Type Window}}, Path=Name}"                                                                                                            
                           Grid.Column="0"
                           FontSize="{DynamicResource SmallSize}"
                           TextWrapping="Wrap" ........................

回答by Eugene

{Binding RelativeSource = {RelativeSource FindAncestor,
                           AncestorType={x:Type Window}}, Path=Name}

Here you say to WPF find first parent of this control with Type Window, e.g. it's "ParentWindow". After this binding occurs to "ParentWindow" Name property.

在这里,您对 WPF 使用 Type Window 查找此控件的第一个父级,例如它是“ParentWindow”。在此绑定发生到“ParentWindow”Name 属性之后。

If you want enable binding to control, which defined in same XAML, you can set the source explicitly by using Binding.ElementName property. This is example for you code:

如果要启用在同一 XAML 中定义的控件绑定,可以使用 Binding.ElementName 属性显式设置源。这是您的代码示例:

<TextBlock Text = "{Binding ElementName=Name, Path=Text}"/>

By the way, using control name as "Name" not is good. If you use this control form code behind it's looking as Name.Text = "some text", which can cause a trouble to understand what is going on.

顺便说一句,使用控件名称作为“名称”不是很好。如果您在其背后使用此控件表单代码,则它看起来像 Name.Text = "some text",这可能会导致难以理解正在发生的事情。

UPDATE:Example of binding to control DataContext Property in different datatemplate

更新:绑定到控制不同数据模板中的 DataContext 属性的示例

class MainViewModel
{
    public Class1 C1 { get; set; }
    public Class2 C2 { get; set; }

    public MainViewModel()
    {
        C1 = new Class1 { S1 = "This is C1 data context" };
        C2 = new Class2 { S2 = "This is C2 data context" };
    }
}

In XAML:

在 XAML 中:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"        
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <DataTemplate DataType="{x:Type local:MainViewModel}">
            <StackPanel>
                <ContentControl Name="cc1" Content="{Binding C1}"/>
                <ContentControl Name="cc2" Content="{Binding C2}"/>
            </StackPanel>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:Class1}">
            <TextBlock Text="{Binding S1}"/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:Class2}">
            <TextBlock Text="{Binding ElementName=cc1, Path=DataContext.C1.S1}"/>
        </DataTemplate>
    </Window.Resources>

    <Grid>
        <ContentControl Content="{Binding}"/>
    </Grid>
</Window>

But, I don't think something like this is a good approach. Especially, because this can be many items with this DataTemplate. Maybe you need delegate this to your ViewModel.

但是,我不认为这样的事情是一个好方法。特别是,因为这可以是具有此 DataTemplate 的许多项目。也许您需要将其委托给您的 ViewModel。