Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从DataTemplate创建实例_C#_Wpf_Listview_Datatemplate - Fatal编程技术网

C# 如何从DataTemplate创建实例

C# 如何从DataTemplate创建实例,c#,wpf,listview,datatemplate,C#,Wpf,Listview,Datatemplate,我已经实现了一个自定义控件,它在控件模板内部使用ListView。FindParts可以访问此列表视图。我需要将ListViews视图属性设置为必须在自定义控件中以编程方式实例化的实例。我希望能够从可以绑定到自定义控件属性的DataTemplate创建此实例 问题是我不知道如何从DataTemplate创建实例 请注意,我不想将GridView直接绑定到View属性(例如,从ResourceDictionary中,DataTemplates x:Shared属性设置为false),因为这会导致X

我已经实现了一个自定义控件,它在控件模板内部使用ListView。FindParts可以访问此列表视图。我需要将ListViews视图属性设置为必须在自定义控件中以编程方式实例化的实例。我希望能够从可以绑定到自定义控件属性的DataTemplate创建此实例

问题是我不知道如何从DataTemplate创建实例

请注意,我不想将GridView直接绑定到View属性(例如,从ResourceDictionary中,DataTemplates x:Shared属性设置为false),因为这会导致XAML设计器中出现问题(视图不能由多个ListView共享)


编辑:在我与grek40的讨论中,很明显,无法在DataTemplate中提供GridView。因此,标记为solution的答案不会处理我的问题标题所暗示的如何从DataTemplate创建实例的问题

您可以实现自己的DataTemplateSelector,然后动态创建一次性使用的DataTemplate,大致如下所示:

public DataTemplate GenerateTemplate() {
  var template = new DataTemplate();
  var p = new FrameworkElementFactory(typeof(Grid));
  p.SetValue(FrameworkElement.HorizontalAlignmentProperty, HorizontalAlignment.Left);
  p.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center);
  ...
  template.VisualTree = p;
  return template;
}

因为你没有分享太多的代码,所以我凭空做了一些东西。其思想是:
MyCustomControl
托管项目,为此,在
ControlTemplate
中使用了
ListView
。默认的
GridView
直接包含在
ControlTemplate
中,但是可以通过
MyCustomControl.MyView

自定义控件:

public class MyCustomControl : ItemsControl
{
    static MyCustomControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl)));
    }


    public ViewBase MyView
    {
        get { return (ViewBase)GetValue(MyViewProperty); }
        set { SetValue(MyViewProperty, value); }
    }

    public static readonly DependencyProperty MyViewProperty =
        DependencyProperty.Register("MyView", typeof(ViewBase), typeof(MyCustomControl), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnMyViewChanged)));

    private static void OnMyViewChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((MyCustomControl)d).HasCustomView = e.NewValue != null;
    }



    // readonly property to support the Trigger in the ControlTemplate in order to exchange the ListView.View
    public bool HasCustomView
    {
        get { return (bool)GetValue(HasCustomViewProperty); }
        private set { SetValue(HasCustomViewPropertyKey, value); }
    }

    private static readonly DependencyPropertyKey HasCustomViewPropertyKey =
        DependencyProperty.RegisterReadOnly("HasCustomView", typeof(bool), typeof(MyCustomControl), new PropertyMetadata(false));
    public static readonly DependencyProperty HasCustomViewProperty = HasCustomViewPropertyKey.DependencyProperty;
}
控件模板(请注意默认的GridView和用于替换的触发器):

编辑2,针对已评论的MCVE:

我将完全按照我在第一次编辑中解释的那样解决这个问题。将控件转换为
数据模板
,而不是将视图转换为样式

在MainWindow.xaml中替换:

<!-- old -->
<myctrls:MyControl Grid.Row="0" Grid.Column="0" Style="{StaticResource AddressStyle}" ItemsSource="{Binding Addresses}"/>
<!-- new -->
<ContentControl Grid.Row="0" Grid.Column="0" ContentTemplate="{StaticResource AddressTemplate}" Content="{Binding Addresses}"/>
新的:


对于
产品样式
,执行相同的步骤


如果你不喜欢<代码> Cordon控件 AddiSListTistVIEW模型”。这将允许您通过

DataType
来处理
DataTemplate
,而不是
ContentControl
中的资源键和显式用法。类型为
ViewBase
,因此如果要将此部件从外部传递到CustomControl,则需要此类型的属性。也许一些示例代码有助于理解在这整个过程中,您希望数据模板在哪里。是的,您是对的。目前,我有一个ViewBase类型的DependencyProperty。在ResourceDictionary中,我拥有该属性的资源和样式,并使用Setter来分配这些资源。正如我上面提到的,我必须将x:Shared=false设置为使这些资源在运行时可用,但它们在设计时会导致问题。现在我想更改控件以接受包含GridView定义的DataTemplate。然后,控件需要创建DataTemplate的实例。我的问题是如何从DataTemplate创建实例。是否有理由不只是绑定listview的itemsource和Itemtemplate?该控件是一个AutoCompleteLookup。它可以设置样式以支持不同的数据类型。显示建议时,项目可以用列显示。对于某些数据类型,它将只显示一列,而对于其他数据类型,它可以显示多个列。为了能够定义不同的列,我必须能够交换ListView视图。我需要用另一种方式来交换。我需要从已分配给海关控制属性的DataTemplate创建一个实例。您的代码与我的问题非常接近。很抱歉,我没有想到类似的东西。由于控件用于不同类型的项,我在ResourceDictionary中为它们定义了一些样式:
这在运行时有效,但在设计时的某些条件下,XAML设计器显示错误“视图不能由多个ListView共享”。为了解决这个问题,我想引入DataTemplate类型的依赖属性。然后,我将GridView资源包装到DataTemplates中,而不是将GridView实例分配给MyView属性,而是将这些DataTemplates分配给新属性。在用户控件的OnApplyTemplate方法中,我想创建一个与数据模板匹配的实例,并将其分配给MyView属性。@E812只需考虑上面的一个级别。例如,为地址数据制作一个
DataTemplate
,但在
AutoCompleteLookup
级别上,而不是在
AutoCompleteLookup.View
级别上。它不应该有太多额外的代码,而且它会工作得更好,因为视图级别不适合作为
DataTemplate
。或者,向下一级,改为使用
ItemTemplate
。@E812添加了一个带有
DataTemplate
的示例。如果这不是正确的方向,你真的必须给出一个完整的MCVE。
<local:MyCustomControl>
    <!--uses default view-->
    <TextBlock Text="Item 1"/>
    <TextBlock Text="Item 2"/>
</local:MyCustomControl>

<local:MyCustomControl>
    <!--uses custom view-->
    <local:MyCustomControl.MyView>
        <GridView>
            <GridView.Columns>
                <GridViewColumn Header="ABC"/>
            </GridView.Columns>
        </GridView>
    </local:MyCustomControl.MyView>
    <TextBlock Text="Item 1"/>
    <TextBlock Text="Item 2"/>
</local:MyCustomControl>
<StackPanel>
    <StackPanel.Resources>
        <x:Array x:Key="Items1" Type="{x:Type sys:Int32}">
            <sys:Int32>1</sys:Int32>
            <sys:Int32>2</sys:Int32>
            <sys:Int32>3</sys:Int32>
            <sys:Int32>4</sys:Int32>
        </x:Array>

        <x:Array x:Key="Items2" Type="{x:Type sys:Int32}">
            <sys:Int32>5</sys:Int32>
            <sys:Int32>4</sys:Int32>
            <sys:Int32>6</sys:Int32>
            <sys:Int32>7</sys:Int32>
        </x:Array>

        <CollectionViewSource x:Key="ItemsSource1" Source="{StaticResource Items1}"/>
        <CollectionViewSource x:Key="ItemsSource2" Source="{StaticResource Items2}"/>

        <DataTemplate x:Key="IntegerListTemplate1">
            <local:MyCustomControl ItemsSource="{Binding}">
                <!--uses default view-->
            </local:MyCustomControl>
        </DataTemplate>

        <DataTemplate x:Key="IntegerListTemplate2">
            <local:MyCustomControl ItemsSource="{Binding}">
                <!--uses custom view-->
                <local:MyCustomControl.MyView>
                    <GridView>
                        <GridView.Columns>
                            <GridViewColumn Header="ABC"/>
                        </GridView.Columns>
                    </GridView>
                </local:MyCustomControl.MyView>
            </local:MyCustomControl>
        </DataTemplate>
    </StackPanel.Resources>
    <!--the default view-->
    <ContentControl ContentTemplate="{StaticResource IntegerListTemplate1}" Content="{Binding Source={StaticResource ItemsSource1}}"/>
    <Separator Margin="3"/>
    <!--same items other view-->
    <ContentControl ContentTemplate="{StaticResource IntegerListTemplate2}" Content="{Binding Source={StaticResource ItemsSource1}}"/>
    <Separator Margin="3"/>
    <!--different items same view as second one, no complaints about reusing-->
    <ContentControl ContentTemplate="{StaticResource IntegerListTemplate2}" Content="{Binding Source={StaticResource ItemsSource2}}"/>
</StackPanel>
<!-- old -->
<myctrls:MyControl Grid.Row="0" Grid.Column="0" Style="{StaticResource AddressStyle}" ItemsSource="{Binding Addresses}"/>
<!-- new -->
<ContentControl Grid.Row="0" Grid.Column="0" ContentTemplate="{StaticResource AddressTemplate}" Content="{Binding Addresses}"/>
<GridView x:Key="AddressGridView" x:Shared="False">
    <GridViewColumn Header="City" Width="Auto" >
        <GridViewColumn.CellTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding City}" HorizontalAlignment="Left"/>
            </DataTemplate>
        </GridViewColumn.CellTemplate>
    </GridViewColumn>
    <GridViewColumn Header="Country" Width="Auto" >
        <GridViewColumn.CellTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Country}" HorizontalAlignment="Left"/>
            </DataTemplate>
        </GridViewColumn.CellTemplate>
    </GridViewColumn>
</GridView>

<Style x:Key="AddressStyle" TargetType="{x:Type myctrls:MyControl}">
    <Setter Property="SuggestionsView" Value="{DynamicResource AddressGridView}"/>
</Style>
<DataTemplate x:Key="AddressTemplate">
    <!-- the base control -->
    <myctrls:MyControl ItemsSource="{Binding}">
        <!-- this was previously assigned by AddressStyle -->
        <myctrls:MyControl.SuggestionsView>
            <!-- this was previously the AddressGridView -->
            <!-- Same as before, only removed the x:Key and x:Shared -->
            <GridView>
                <GridViewColumn Header="City" Width="Auto" >
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding City}" HorizontalAlignment="Left"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="Country" Width="Auto" >
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Country}" HorizontalAlignment="Left"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </myctrls:MyControl.SuggestionsView>
    </myctrls:MyControl>
</DataTemplate>