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

Wit*_*tle 5 c# wpf xaml windows-phone-8 visual-studio-2013

我正在尝试在文本下方创建多个按钮,并在运行时将它们添加到代码中的Stackpanel中。我基于数据列表创建按钮。这是我的代码:

XAML

<StackPanel x:Name="MainSP" />
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

我知道这是笨拙的编程。我真的很想在XAML中设置ControlTemplate,然后在代码中创建按钮时重用它。这是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>
Run Code Online (Sandbox Code Playgroud)

我已经尝试过使用上述的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);
}
Run Code Online (Sandbox Code Playgroud)

对于数据上下文,我也尝试过,newBtn.DataContext = ItemList[itemIndex]但这似乎没有用。我所得到的只是一个空白屏幕。

因此,我已经通过按钮创建背后的纯代码找出了问题,但是我正在尝试使用XAML控件模板来使其正常工作。有什么想法吗?

谢谢!

Fed*_*gui 3

在 WPF 中的过程代码中创建或操作 UI 元素几乎是never正确的方法。

在某些例外情况下,这会很有用,但您呈现的这种情况是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>
Run Code Online (Sandbox Code Playgroud)

背后代码:

    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.
    }
Run Code Online (Sandbox Code Playgroud)
  • 使用 ItemsControl,您可以让 WPF 为每个项目创建 UI,而不是您自己创建。
  • 每个按钮DataContext也将由 WPF 设置为基础集合中的相应数据项。
  • 无需诉诸可怕的技巧来使用Tag财产或类似的事情。
  • StackPanel默认的ItemsPanel,但您可以通过设置ItemsControl将其更改为另一个面板(例如)WrapPanelItemsPanel