在 DataTemplate 中查找应用于 TabItem 的元素

发布于 2024-08-01 20:50:13 字数 4584 浏览 4 评论 0原文

我在尝试查找 DataTemplate 中声明的元素时遇到问题,该元素像 ContentTemplate 一样应用于 TabItem 对象。 我看到已经有一些关于这个问题的解决方案,但没有一个真正适用于我的情况,我想了解为什么(显然我在某些地方犯了错误) 下面是一个示例代码:

<DataTemplate x:Key="TabItemDataTemplate">             
    <Grid HorizontalAlignment="Stretch" 
        VerticalAlignment="Stretch" Name="templateGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="6.0*"> </RowDefinition>
            <RowDefinition Height="6" ></RowDefinition>
            <RowDefinition Height="6.0*" ></RowDefinition>
            <RowDefinition Height="*" ></RowDefinition>
        </Grid.RowDefinitions>                

        <ListView x:Name="repoView" Grid.Row="0" 
            VerticalAlignment="Stretch"
            ItemsSource="{Binding Source={StaticResource  DataProviderForListView}}">                        
            <GridView>
                <GridViewColumn Header="State"
                    DisplayMemberBinding="{Binding Path=RepositoryItemState}"/>
                <GridViewColumn Header="Working Copy Rev num."
                    DisplayMemberBinding="{Binding Path=WCRevision}"/>
                <GridViewColumn Header="Repository Rev num."
                    DisplayMemberBinding="{Binding Path=RepoRevision}"/>
                <GridViewColumn Header="User"
                    DisplayMemberBinding="{Binding Path=Account}"/>
                <GridViewColumn Header="Item"
                    DisplayMemberBinding="{Binding Path=ItemName}"/>
            </GridView>
        </ListView>

        <GridSplitter x:Name="gridSplitter" Grid.Row="1"
            ResizeDirection="Rows" Background="Gray" 
            Height="4" HorizontalAlignment="Stretch"
            Style="{StaticResource gridSplitterStyle}"/>

        <RichTextBox x:Name="rowView" Grid.Row="2" 
            BorderBrush="Bisque" VerticalAlignment="Stretch"
            IsReadOnly="True" Background="YellowGreen"
            FontFamily="Comic Sans Serif"/>


        <ToggleButton x:Name="rbWorkingCopy"
            Template="{StaticResource ToggleButtonControlTemplate}"
            Grid.Row="3" Width="100" Height="22"
            Content="{StaticResource WorkingCopyTitle}"
            HorizontalAlignment="Left" VerticalAlignment="Bottom"
            Command="repoManager:AppCommands.GetWorkingCopyInfoCommand" />
        <ToggleButton x:Name="rbRepository"
            Template="{StaticResource ToggleButtonControlTemplate}"
            Grid.Row="3"  Width="100" Height="22"
            Content="{StaticResource  RepositoryTitle}"
            HorizontalAlignment="Left"
            VerticalAlignment="Bottom"  Margin="120,0,0,0" 
            Command="repoManager:AppCommands.GetRepoInfoCommand" />
        <ProgressBar x:Name="checkRepositoryProgress" Grid.Row="3"
            Width="220" Height="22" HorizontalAlignment="Right"  
            VerticalAlignment="Bottom" Margin="250,0,10,0"
            IsIndeterminate="True"
            IsEnabled="{Binding repoManager:ExecutingCommand}"  />
    </Grid>
</DataTemplate>

该代码通过以下方式以编程方式应用于给定的 TabItem 对象:

this.ContentTemplate = FindResource("TabItemDataTemplate") as DataTemplate;

在我需要访问 DataTemplate 中声明的 ListView 元素之后,我执行在互联网以及此站点上找到的代码。 下面是一个简短的示例:

/* Getting the ContentPresenter of myListBoxItem*/          
ContentPresenter myContentPresenter =
    FindVisualChild<ContentPresenter>(this);

// this.GetVisualChild(0)
/* Finding textBlock from the DataTemplate that is set on that ContentPresenter*/
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;

ListView repoListView = (ListView)myDataTemplate.FindName("repoView", 
    myContentPresenter);

问题1:在这种情况下,ContentPresenter 的 ContentTemplate 为 Null,因此代码执行崩溃。 问题2:好吧,我想,可能我需要直接导航抛出TabItem内容,所以代码或多或少变成:

/* Getting the ContentPresenter of myListBoxItem*/          
ContentPresenter myContentPresenter =
    FindVisualChild<ContentPresenter>(this);

// this.GetVisualChild(0)
/* Finding textBlock from the DataTemplate that is set on that ContentPresenter*/
DataTemplate myDataTemplate = this.ContentTemplate;

ListView repoListView = (ListView)myDataTemplate.FindName("repoView", 
    myContentPresenter);

this 是TabItem对象。 但奇怪的是,this 的 ContentTemplate 与上面指定的完全不同。 我确信我在某个地方遗漏了一些东西,你能帮我找出问题所在吗? 谢谢。

I got a problem trying to find an element declared in DataTemplate, that after was applied like a ContentTemplate to TabItem object.
I saw that there is already some solutions in regard of this problem, but no one of them actually works in my case, and I would like to understand why (obviously I make mistake in some place)
Here is a sample code:

<DataTemplate x:Key="TabItemDataTemplate">             
    <Grid HorizontalAlignment="Stretch" 
        VerticalAlignment="Stretch" Name="templateGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="6.0*"> </RowDefinition>
            <RowDefinition Height="6" ></RowDefinition>
            <RowDefinition Height="6.0*" ></RowDefinition>
            <RowDefinition Height="*" ></RowDefinition>
        </Grid.RowDefinitions>                

        <ListView x:Name="repoView" Grid.Row="0" 
            VerticalAlignment="Stretch"
            ItemsSource="{Binding Source={StaticResource  DataProviderForListView}}">                        
            <GridView>
                <GridViewColumn Header="State"
                    DisplayMemberBinding="{Binding Path=RepositoryItemState}"/>
                <GridViewColumn Header="Working Copy Rev num."
                    DisplayMemberBinding="{Binding Path=WCRevision}"/>
                <GridViewColumn Header="Repository Rev num."
                    DisplayMemberBinding="{Binding Path=RepoRevision}"/>
                <GridViewColumn Header="User"
                    DisplayMemberBinding="{Binding Path=Account}"/>
                <GridViewColumn Header="Item"
                    DisplayMemberBinding="{Binding Path=ItemName}"/>
            </GridView>
        </ListView>

        <GridSplitter x:Name="gridSplitter" Grid.Row="1"
            ResizeDirection="Rows" Background="Gray" 
            Height="4" HorizontalAlignment="Stretch"
            Style="{StaticResource gridSplitterStyle}"/>

        <RichTextBox x:Name="rowView" Grid.Row="2" 
            BorderBrush="Bisque" VerticalAlignment="Stretch"
            IsReadOnly="True" Background="YellowGreen"
            FontFamily="Comic Sans Serif"/>


        <ToggleButton x:Name="rbWorkingCopy"
            Template="{StaticResource ToggleButtonControlTemplate}"
            Grid.Row="3" Width="100" Height="22"
            Content="{StaticResource WorkingCopyTitle}"
            HorizontalAlignment="Left" VerticalAlignment="Bottom"
            Command="repoManager:AppCommands.GetWorkingCopyInfoCommand" />
        <ToggleButton x:Name="rbRepository"
            Template="{StaticResource ToggleButtonControlTemplate}"
            Grid.Row="3"  Width="100" Height="22"
            Content="{StaticResource  RepositoryTitle}"
            HorizontalAlignment="Left"
            VerticalAlignment="Bottom"  Margin="120,0,0,0" 
            Command="repoManager:AppCommands.GetRepoInfoCommand" />
        <ProgressBar x:Name="checkRepositoryProgress" Grid.Row="3"
            Width="220" Height="22" HorizontalAlignment="Right"  
            VerticalAlignment="Bottom" Margin="250,0,10,0"
            IsIndeterminate="True"
            IsEnabled="{Binding repoManager:ExecutingCommand}"  />
    </Grid>
</DataTemplate>

This code is porgrammatically applied to the given TabItem object in following way :

this.ContentTemplate = FindResource("TabItemDataTemplate") as DataTemplate;

After I need access to the ListView element declared in DataTemplate, so I execute the codes found around in internet, and also on this site. Here is a short example:

/* Getting the ContentPresenter of myListBoxItem*/          
ContentPresenter myContentPresenter =
    FindVisualChild<ContentPresenter>(this);

// this.GetVisualChild(0)
/* Finding textBlock from the DataTemplate that is set on that ContentPresenter*/
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;

ListView repoListView = (ListView)myDataTemplate.FindName("repoView", 
    myContentPresenter);

Problem1: In this case ContentTemplate of ContentPresenter is Null, so code execution crashes.
Prolem2: Ok, I think, may be I need to navigate throw TabItem content directly, so the code becomes, more or less:

/* Getting the ContentPresenter of myListBoxItem*/          
ContentPresenter myContentPresenter =
    FindVisualChild<ContentPresenter>(this);

// this.GetVisualChild(0)
/* Finding textBlock from the DataTemplate that is set on that ContentPresenter*/
DataTemplate myDataTemplate = this.ContentTemplate;

ListView repoListView = (ListView)myDataTemplate.FindName("repoView", 
    myContentPresenter);

this is TabItem object. But the strage things, that the ContentTemplate of this is completely different from that one assigned above. I'm sure that I missed something somewhere, can you help me to figure out the problem ?
Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

予囚 2024-08-08 20:50:13

简而言之,如果您有一个 DataGrid 和一个包含数据模板的 TemplateColumn,则可以使用以下代码示例:

<DataGridTemplateColumn x:Name="photoPathColumn" Header="{x:Static resx:FrmResource.Photo}" Width="Auto">
    <DataGridTemplateColumn.CellEditingTemplate x:Uid="keyelm">
        <DataTemplate x:Name="dodo">
            <StackPanel Orientation="Horizontal" Height="Auto">
                <TextBlock x:Name="photo" x:Uid="imageFile" Text="{Binding Path=PhotoPath}"></TextBlock>
                <Button x:Name="Browse" Content="..." Click="Browse_Click"></Button>
            </StackPanel>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>

TextBlock tBlock = (TextBlok)photoPathColumn.CellEditingTemplate.FindName(
                       "photo",
                       photoPathColumn.GetCellContent(CustomersDataGrid.CurrentItem));
  • 其中 photo 是文本块的名称
  • 其中 photoPathColumnDataGridTemplateColumn

Simply, if you have a DataGrid, and a TemplateColumn which contains a data template, you can use the following code sample:

<DataGridTemplateColumn x:Name="photoPathColumn" Header="{x:Static resx:FrmResource.Photo}" Width="Auto">
    <DataGridTemplateColumn.CellEditingTemplate x:Uid="keyelm">
        <DataTemplate x:Name="dodo">
            <StackPanel Orientation="Horizontal" Height="Auto">
                <TextBlock x:Name="photo" x:Uid="imageFile" Text="{Binding Path=PhotoPath}"></TextBlock>
                <Button x:Name="Browse" Content="..." Click="Browse_Click"></Button>
            </StackPanel>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>

TextBlock tBlock = (TextBlok)photoPathColumn.CellEditingTemplate.FindName(
                       "photo",
                       photoPathColumn.GetCellContent(CustomersDataGrid.CurrentItem));
  • Where photo is the name of text block
  • Where photoPathColumn is the DataGrid's TemplateColumn.
呆头 2024-08-08 20:50:13

好的,我们来了:)
我以不太好的方式解决了这个问题,但似乎工作正常。
正如我上面提到的,我使用了 LoadContent 方法,它返回给我 ListView 对象,但顺便说一句,它不是 UI 实际使用的 ListView。 因此,为了解决这个问题,我添加静态属性来保存我的 REAL ListView 对象(静态,因为我有单个 DataTemplate,其中包含跨多个 TabItem 共享的 ListView,因此 ListView 也共享)并将事件处理程序添加到我的 DataTemplate -> 已加载。 捕获此事件,在我的例子中,仅在应用程序的生命周期中引发事件,在 RoatedEvent's OriginalSource 中,我得到了 WPF 引擎用于在 UI 上呈现的 REAL ListView 对象。
希望我的解决方案能帮助某人。
谢谢你们。

Ok, here we come :)
I resolve the problem, in not very nice way, but it seems that works correctly.
As I mentioned above I used LoadContent method and it returns me the ListView object, but by the way it wasn't the ListView that UI actually uses. So to resolve that problem I add static property to hold my REAL ListView object (static as I have single DataTemplate that contains ListView shared across multiple TabItems, so the ListView shared too) and add event handler to my DataTemplate -> Loaded. Catching this event, that in my case raises only ones in lifetime of application, in RoutedEvent's OriginalSource I got the REAL ListView object that WPF engine uses for rendering on UI.
Hope my solution will help someone.
Thank you all.

孤城病女 2024-08-08 20:50:13

您不想使用 TabItem 的任何模板属性,因为这些属性用于创建实际控件,而不是存储它们。 您应该能够直接在可视化树中搜索 ListView,而不是通过 DataTemplate

You don't want to use any of the template properties of the TabItem, since those are used to create the actual controls, rather than storing them. You should be able to search the visual tree for the ListView directly, rather than going through the DataTemplate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文