none
关于DataTemplateSelector的问题 RRS feed

  • 问题

  • 有几个关于DataTemplateSelector的问题:

    1 SelectTemplate方法和SelectTemplateCore方法的区别

    2 在WPF中使用到的方法

          public override DataTemplate
                SelectTemplate(object item, DependencyObject container)
            {
                FrameworkElement element = container as FrameworkElement;
                if (element != null && item != null && item is Task)
                {
                    Task taskitem = item as Task;
                    if (taskitem.Priority == 1)
                        return
                            element.FindResource("importantTaskTemplate") as DataTemplate;
                    else
                        return
                            element.FindResource("myTaskTemplate") as DataTemplate;
                }
                return null;
            }

    其中(element.FindResource("importantTaskTemplate") as DataTemplate;)现在可以用什么方法代替?

    2012年6月4日 7:05

答案

  • 我回复中的第一段已经说了:

    我们通常把DataTemplate定义在Page或者较高层的Resources中,所以我们需要所定义的那一层的元素才可以通过Resources["key"] 来取到DataTemplate。 

    FindName也是一样,你并没有将你的resource定义在这里的element下,而是Page下的,所以你只有通过Page.FindName和Page.Resoruces[]


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年6月6日 3:06
    版主

全部回复

  • 追加一个问题:在WIN8中,x:name和x:Key还有区别吗?
    2012年6月4日 7:25
  • element.Resources["key"] as DataTemplate 即可。

    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年6月5日 8:47
    版主
  • 追加一个问题:在WIN8中,x:name和x:Key还有区别吗?

    有,文档  http://msdn.microsoft.com/en-us/library/windows/apps/hh758294.aspx  中

    x:Key and x:Name are not identical concepts. x:Key is used exclusively in resource dictionaries. x:Name is used for all areas of XAML. A FindName call using a key value will not retrieve a keyed resource.

    x:Key仅限于资源字典中,x:Name可以用于所有范围的XAML,所以FindName可以适用于用x:Name标记的资源,但不能用于用x:Key标记的。

    你的第一个问题还有一个答案是:

    用x:Name标记,然后 element.FindName("name") as DataTemplate


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年6月5日 8:55
    版主
  • element.Resources["key"] as DataTemplate

    报错为:{"Error HRESULT E_FAIL has been returned from a call to a COM component."}

    element.FindName("name") as DataTemplate

    返回值为null

    2012年6月5日 9:35
  • 我们通常把DataTemplate定义在Page或者较高层的Resources中,所以我们需要所定义的那一层的元素才可以通过Resources["key"] 来取到DataTemplate。 既然我们不方便在 TemplateSelector中定义获得当前的Page实例,那么我们可以将我们的DataTempate资源定义在App.xaml中,然后用 App.Current.Resources["DT1"] as DataTemplate; 即可。

    或者如下设计也可以, 添加一个Page类型属性在TemplateSelector中去获得当前Page实例,然后通过这个实例去找到资源:

            <local:MyTemplateSelector x:Name="templateSelector"/>
            <DataTemplate x:Name="DT3">
                <TextBlock Text="{Binding Name}" Foreground="Red"/>
            </DataTemplate>
            <DataTemplate x:Name="DT4">
                <TextBlock Text="{Binding Name}" Foreground="Green"/>
            </DataTemplate>
        </Page.Resources>
        <Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
            <ListBox ItemsSource="{Binding}" ItemTemplateSelector="{StaticResource templateSelector}">
            </ListBox>
        </Grid>

    C#:

        public sealed partial class BlankPage : Page
        {
            public BlankPage()
            {
                this.InitializeComponent();
                this.DataContext = new List<Item>()
                {
                    new Item(){Name="Name 1", IS=true},
                    new Item(){Name="Name 2", IS=false},
                    new Item(){Name="Name 3", IS=true},
                    new Item(){Name="Name 4", IS=false},
                    new Item(){Name="Name 5", IS=true},
                    new Item(){Name="Name 6", IS=false},
                    new Item(){Name="Name 7", IS=true}
                };
              MyTemplateSelector ts =  this.FindName("templateSelector") as MyTemplateSelector;
              ts.HostedPage = this;
            }
        }
        public class Item
        {
            public string Name { get; set; }
            public bool IS { get; set; }
        }
        public class MyTemplateSelector : DataTemplateSelector
        {
            public Page HostedPage { get; set; }
            protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
            {
                FrameworkElement element = container as FrameworkElement;
                if (element != null && item != null && item is Item)
                {
                    Item taskitem = item as Item;
                    if (taskitem.IS)
                        return HostedPage.FindName("DT3") as DataTemplate;
                    else
                        return HostedPage.FindName("DT4") as DataTemplate;
                }
                return null;
            }
        }


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年6月5日 17:12
    版主
  • 其实对于这个问题,已经找到了其他解决方法。如下所示:

     <Page.Resources>
           <CollectionViewSource x:Name="myTodoList"/>
            <DataTemplate x:Name="importantTaskTemplate">
                <Border Name="border" BorderBrush="Red" BorderThickness="1"
                  Padding="5" Margin="5">
                    <StackPanel HorizontalAlignment="Center">
                        <TextBlock Text="{Binding Path=Description}" />
                        <TextBlock>!</TextBlock>
                    </StackPanel>
                </Border>
            </DataTemplate>
            <DataTemplate x:Name="myTaskTemplate">
                <Border Name="border" BorderBrush="Aqua" BorderThickness="1"
                  Padding="5" Margin="5">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition />
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.Row="0" Grid.Column="0" Text="Task Name:"/>
                        <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=TaskName}" />
                        <TextBlock Grid.Row="1" Grid.Column="0" Text="Description:"/>
                        <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}"/>
                        <TextBlock Grid.Row="2" Grid.Column="0" Text="Priority:"/>
                        <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Priority}"/>
                    </Grid>
                </Border>
            
            </DataTemplate>
            
           <local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector" 
                                                importantTaskTemplate="{StaticResource importantTaskTemplate}"
                                                myTaskTemplate="{StaticResource myTaskTemplate}"/>
        </Page.Resources>

     public class TaskListDataTemplateSelector : DataTemplateSelector
        {
            public DataTemplate importantTaskTemplate { get; set; }
            public DataTemplate myTaskTemplate { get; set; }
            protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
            {
                FrameworkElement element = container as FrameworkElement;
                
                if (element != null && item != null && item is Task)
                {
                    Task taskitem = item as Task;
                    if (taskitem.Priority == 1)
                    {
                        return importantTaskTemplate;
                    }
                            
                    else
                    {
                        return myTaskTemplate;
                    }                        
                }
                return null;
            }
        }
    只是想了解下为什么   var dd = element.FindName("myTaskTemplate") as DataTemplate;

    var dd = element.Resources["myTaskTemplate"] as DataTemplate;不能实现呢!!
    2012年6月6日 2:42
  • 我回复中的第一段已经说了:

    我们通常把DataTemplate定义在Page或者较高层的Resources中,所以我们需要所定义的那一层的元素才可以通过Resources["key"] 来取到DataTemplate。 

    FindName也是一样,你并没有将你的resource定义在这里的element下,而是Page下的,所以你只有通过Page.FindName和Page.Resoruces[]


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年6月6日 3:06
    版主