简体   繁体   English

如何从XAML中定义的数据模板以编程方式创建元素?

[英]How do you create an element programmatically from a data template defined in XAML?

I'm trying to create multiple button with text underneath and have them added to a Stackpanel in code during runtime. 我正在尝试使用下面的文本创建多个按钮,并在运行时将它们添加到代码中的Stackpanel。 I create the buttons based on a List of data. 我根据数据列表创建按钮。 Here's my code: 这是我的代码:

XAML XAML

<StackPanel x:Name="MainSP" />

C# C#

foreach (item in ItemList)
{
    Button newBtn = new Button();
    Image buttonImage = new Image();
    buttonImage.Width = 100;
    buttonImage.Height = 100;
    buttonImage.Stretch = Systems.Windows.Media.Stretch.Uniform;
    buttonImage.Source = new BitmapImage(pokemon.ImageURI);
    newBtn.Tag = item.Id;
    newBtn.Name = String.Format("{0}Button", item.Name);
    newBtn.Click += new RoutedEventHandler(newBtn_Click);

    FamilyStackPanel.Children.Add(newBtn);
}

I know this is clunky programming. 我知道这是笨重的编程。 I really want to set up a ControlTemplate in XAML then reuse that when creating the buttons in code. 我真的想在XAML中设置一个ControlTemplate,然后在代码中创建按钮时重用它。 Here's the XAML: 这是XAML:

<ControlTemplate x:Key="ButtomTemplate" TargetType="Button">
        <Grid Height="108" Width="Auto" Margin = "6,6">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Image Width = "54" Height="54" Stretch="UniformToFill" Grid.Row="0">
                <Image.Source>
                    <BitmapImage UriSource="{Binding ImageUri}" CreateOptions="BackgroundCreation"/>
                </Image.Source>
            </Image>
            <TextBlock Text="{Binding Name}"
                    Foreground ="{StaticResource PhoneAccentBrush}" />
        </Grid>
</ControlTemplate>

I've tried using the controlTemplate like above and then for the bindings, I set the newbtn.DataContext in code. 我尝试过像上面那样使用controlTemplate然后进行绑定,我在代码中设置了newbtn.DataContext。

foreach (Families item in ItemList)
{
    Button newBtn = new Button();
    newBtn.Template = this.Resources["ButtonTemplate"] as ControlTemplate;
    newBtn.Tag = item.Id;
    newBtn.Name = String.Format("{0}Button", item.Name);
    newBtn.Click += new RoutedEventHandler(newBtn_Click);
    newBtn.DataContext = item;

    FamilyStackPanel.Children.Add(newBtn);
}

For the data context I've also attempted newBtn.DataContext = ItemList[itemIndex] but that didn't seem to work. 对于数据上下文,我还尝试了newBtn.DataContext = ItemList[itemIndex]但这似乎不起作用。 All I get is a blank screen. 我得到的只是一个空白屏幕。

So I've figured it out through pure code behind button creation, but I'm trying to use XAML control templates to make it work. 所以我通过创建按钮后的纯代码来解决它,但我正在尝试使用XAML控件模板来使其工作。 Have any ideas? 有什么想法吗?

Thank you! 谢谢!

Creating or manipulating UI elements in procedural code in WPF is almost never the correct way. 在WPF中的过程代码中创建或操作UI元素几乎never正确的方法。

There are exceptions where that would be useful, but this case you're presenting is the simplest case for the ItemsControl . 有些例外情况会有用,但是你提出的这种情况是ItemsControl最简单的情况。

<ItemsControl ItemsSource="{Binding ItemList}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Click="Button_OnClick">
                <Button.Template>
                    <ControlTemplate TargetType="Button">
                        <Grid Height="108" Width="Auto" Margin = "6,6">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>
                            <Image Width = "54" Height="54" Stretch="UniformToFill" Grid.Row="0">
                                <Image.Source>
                                    <BitmapImage UriSource="{Binding ImageUri}" CreateOptions="BackgroundCreation"/>
                                </Image.Source>
                            </Image>
                            <TextBlock Text="{Binding Name}"
                                       Foreground ="{StaticResource PhoneAccentBrush}" />
                        </Grid>
                    </ControlTemplate>
                </Button.Template>
            </Button>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Code Behind: 代码背后:

    private void Button_OnClick(object sender, RoutedEventArgs e)
    {
        var button = sender as Button;
        var dataitem = button.DataContext as [YourItemclass];

        //... here you can perform actions on the dataitem.
    }
  • Using an ItemsControl, your let WPF create the UI for each item instead of creating it yourself. 使用ItemsControl,您的让WPF为每个项目创建UI,而不是自己创建。
  • Each Button's DataContext will be also set by WPF to the corresponding data item in the underlying collection. 每个Button的DataContext也将由WPF设置为底层集合中的相应数据项。
  • No need to resort to horrible hacks of using the Tag property or anything like that. 无需诉诸使用Tag属性或类似内容的可怕黑客。
  • The StackPanel is the default ItemsPanel for the ItemsControl , but you can change that to another panel (such as WrapPanel ) by setting the ItemsPanel StackPanelItemsControl的默认ItemsPanel ,但您可以通过设置ItemsPanel将其更改为另一个面板(例如WrapPanel

You can use XamlReader to create xaml with dynamic content. 您可以使用XamlReader创建具有动态内容的xaml。 This way you will be able to set any of the property at runtime. 这样,您就可以在运行时设置任何属性。

http://msdn.microsoft.com/en-us/library/system.windows.markup.xamlreader(v=vs.110).aspx http://msdn.microsoft.com/en-us/library/system.windows.markup.xamlreader(v=vs.110).aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在xaml中自动为数组的每个元素创建框? - How do you create box for each element of array automatically in xaml? 如何以编程方式设置Xaml定义的Window.Resource Image? - How do you set a Xaml defined, Window.Resource Image programmatically? 以编程方式从模板创建元素 - Create an element from template programmatically 您如何以编程方式为模板控件创建默认模板? - How do you programmatically create a default template for a templated control? 您是否可以显示ListBox的第一个元素,而不是为xaml创建数据模板 - Can you display the first element of a ListBox rather than create a data template for xaml 如何从 XAML 中定义的 ResourceDictionary 检索 Brush 并将其应用于代码中的元素? - How can you retrieve a Brush from a ResourceDictionary defined in XAML and apply it to an element in code? 如何在 XAML 中创建工作模板? - How do i create a working Template in XAML? 在WPF中,如何从嵌套用户控件访问Window.xaml中定义的对象? - In WPF how do you access an object defined in Window.xaml from a nested user control? 如何将数据传递到XAML中的IValueConverter? - How do you pass data into an IValueConverter in XAML? XAML-如何以编程方式从迷你标记创建路径? - XAML - How do I programmatically create a Path from mini-markup?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM