• WPF 基础


    1. 在 ControlTemplate 中寻找元素

    <Window.Resources>
        <ControlTemplate x:Key="cTmp">
            <StackPanel>
                <StackPanel.Resources>
                    <Style TargetType="TextBlock">
                        <Setter Property="Margin" Value="6"/>
                    </Style>
                </StackPanel.Resources>
                <TextBlock x:Name="tb1" Text="tb1"/>
                <TextBlock x:Name="tb2" Text="tb2"/>
                <TextBlock x:Name="tb3" Text="tb3"/>
            </StackPanel>            
        </ControlTemplate>
    </Window.Resources>
    
    <StackPanel>
        <UserControl x:Name="uc" Template="{StaticResource cTmp}" />
        <Button Click="Button_Click" Content="FindName" Width="90" Height="25"/>
    </StackPanel>
    
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        TextBlock tb = this.uc.Template.FindName("tb1", this.uc) as TextBlock;
        tb.Text = "I Find the first one";
    
        StackPanel sp = tb.Parent as StackPanel;
        (sp.Children[1] as TextBlock).Text = "I am the second one";
        (sp.Children[2] as TextBlock).Text = "I am the third one";
    }
    

    this.xx.Template.FindName((string)elementName, this.xx) as typeof(elementType);

    2. 在 DateTemplate 中寻找元素

    类似于 ControlTemplate,可以使用
    this.xx.ContentTemplate.FindName(string(elementName), this.xx) as typeof(elementType) 寻找元素;
    但我们一般是为了获取控件的长度、宽度,而不是为了获取内容的某个属性;
    要获取内容的某个属性,不必绕到表层控件上来。

    <Window.Resources>
        <coll:ArrayList x:Key="stuList">
            <local:Student Id="1" Name="Mao1" LoveBasketball="True"></local:Student>
            <local:Student Id="2" Name="Mao2" LoveBasketball="False"></local:Student>
            <local:Student Id="3" Name="Mao3" LoveBasketball="True"></local:Student>
            <local:Student Id="4" Name="Mao4" LoveBasketball="False"></local:Student>
            <local:Student Id="5" Name="Mao5" LoveBasketball="True"></local:Student>
            <local:Student Id="6" Name="Mao6" LoveBasketball="False"></local:Student>
        </coll:ArrayList> 
    
        <DataTemplate x:Key="dtId">
            <TextBlock Text="{Binding Id}"/>
        </DataTemplate>
    
        <DataTemplate x:Key="dtName">
            <TextBox x:Name="textBoxName" Text="{Binding Name}" GotFocus="TextBoxName_GotFocus" />
        </DataTemplate>
    
        <DataTemplate x:Key="dtLoveBasketball">
            <CheckBox x:Name="checkBoxLove" IsChecked="{Binding LoveBasketball}" IsEnabled="False"/>
        </DataTemplate>
      
    </Window.Resources>
    
    <StackPanel MenuItem.Click="StackPanel_Click">
        <ListView x:Name="list_stu" ItemsSource="{StaticResource stuList}">
            <ListView.View>
                <GridView x:Name="ddr">
                    <GridViewColumn Header="Id" CellTemplate="{Binding Source={StaticResource dtId}}"></GridViewColumn>
                    <GridViewColumn x:Name="dd" Header="Name" CellTemplate="{Binding Source={StaticResource dtName}}"></GridViewColumn>
                    <GridViewColumn Header="LoveBasketball" CellTemplate="{Binding Source={StaticResource dtLoveBasketball}}"></GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
    </StackPanel>
    
    private void TextBoxName_GotFocus(object sender, RoutedEventArgs e)
    {
        TextBox tb = e.OriginalSource as TextBox; // 获取事件发起的源头
        ContentPresenter cp = tb.TemplatedParent as ContentPresenter; // 获取模板目标
        Student stu = cp.Content as Student; // 获取业务逻辑数据,[DataTemplate 落实在 ContentPresenter 上,ContentPresenter 是 ControlTemplate 的一个结点]
        this.list_stu.SelectedItem = stu; // 设置 ListView 的选中项
    
        ListViewItem lvi = this.list_stu.ItemContainerGenerator.ContainerFromItem(stu) as ListViewItem;
        CheckBox cb = this.FindVisualChild<CheckBox>(lvi);
    
        Console.WriteLine(cb.Name);
    }
    
    private ChildType FindVisualChild<ChildType>(DependencyObject obj) where ChildType : DependencyObject
    { 
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(obj, i);
    
            if (child != null && child is ChildType)
            {
                return child as ChildType;
            }
            else
            {
                ChildType childOfChild = FindVisualChild<ChildType>(child);
                if (childOfChild != null)
                {
                    return childOfChild;
                }
            }
        }
    
        return null;
    }
    
    • 当使用 GridView 作为 ListView 的 View 属性值,如果某一列使用 TextBox 作为 CellTemplate,那么即使这列中的 TextBox 被鼠标单击并获得焦点,ListView 也不会把此项作为自己的 SelectedItem;
    • 在 ListBox 中 ItemTemplate 下的 TextBox 也是如此;
    • 因此 TextBoxName_GotFocus 先获取事件的最初源头,然后沿着 UI 元素树上溯到 DataTemplate 的目标控件(ContentPresenter)并获取它的内容,必是一个 Student 实例;
    • 使用 ItemsControl 的 ItemContainerGenerator.ContainerFromItem 方法获得包装这指定条目数据的容器 ListViewItem;
    • ListViewItem 的 Content 也是 Student 实例。

    前面 ListViewItem 的可视化树

    graph LR Border1-->ListViewItem Border2-->Border1 Grid-->Border2 Rectangle-->Grid GridViewRowPresenter-->Grid ContentPresenter1-->GridViewRowPresenter TextBlock-->ContentPresenter1 ContentPresenter2-->GridViewRowPresenter TextBox-->ContentPresenter2 ContentPresenter3-->GridViewRowPresenter CheckBox-->ContentPresenter3
    graph LR Border3-->TextBox ScrollViewer-->Border3 Grid2-->ScrollViewer Rectangle2-->Grid2 ScrollContentPresenter-->Grid2 TextBoxView-->ScrollContentPresenter TextBoxLineDrawingVisual-->TextBoxView AdornerLayer-->ScrollContentPresenter ScrollBar-->Grid2 ScrollBar2-->Grid2
    <StackPanel MenuItem.Click="StackPanel_Click">
        <StackPanel.Resources>
            <DataTemplate x:Key="it">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Id}"/>
                    <TextBox x:Name="textBoxName" Text="{Binding Name}" GotFocus="TextBoxName_GotFocus" Margin="15 0"/>
                    <CheckBox x:Name="checkBoxLove" IsChecked="{Binding LoveBasketball}"/>
                </StackPanel>
            </DataTemplate>
            
            <Style TargetType="ListBoxItem">
                <Setter Property="ContentTemplate" Value="{StaticResource it}"/>
                <Style.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Id}" Value="3"/>
                            <Condition Binding="{Binding Name}" Value="Mao3"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Background" Value="Red"></Setter>
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </StackPanel.Resources>
        
        <ListBox x:Name="list_stu2" ItemsSource="{StaticResource stuList}" >
        </ListBox>
    </StackPanel>
    
  • 相关阅读:
    我的作业
    代码练习
    prority_queue 的用法 实例
    最短路问题专题
    键值对 Intent
    P103 任意两点之间的最短路问题 Floyd_warshall算法
    第6届山东省ACM省赛总结
    HDU 3247 Resource Archiver[AC自动机+最短路+dp]
    POJ 2778 DNA Sequence [AC自动机 + 矩阵快速幂]
    HDU 2896 病毒侵袭 [AC自动机]
  • 原文地址:https://www.cnblogs.com/MichaelLoveSna/p/14451033.html
Copyright © 2020-2023  润新知