简体   繁体   中英

XAML outsourcing datatemplate with events in APP.xaml

I'm having a working datatemplate for a ListView with ItemTemplate

<ListView ItemTemplate="{StaticResource MYTEMPLATE}"             
          HorizontalAlignment="Center"
          ScrollViewer.VerticalScrollBarVisibility="Auto"
          ContinuumNavigationTransitionInfo.IsEntranceElement="True">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel VerticalAlignment="Bottom"/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
</ListView>

The Template looks like that:

<DataTemplate x:Key="GlobalBox">
        <Border Background="#FFFFFFFF" Margin="10 0 0 5" CornerRadius="2 2 15 2">
            <Grid Width="380">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <StackPanel Grid.Row="0" Tag="{Binding ID}" Name="ProfileInfo" Tapped="Profile_Tapped" Orientation="Horizontal" Margin="15 15 15 0">
                    <Grid Width="360" Margin="0 0 0 10">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="75"></ColumnDefinition>
                            <ColumnDefinition Width="*"></ColumnDefinition>
                            <ColumnDefinition Width="50"></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <Border Grid.Column="0" Height="45" Width="45" CornerRadius="5">
                            <Border.Background>
                                <ImageBrush ImageSource="{Binding ImagePath}" Stretch="UniformToFill"/>
                            </Border.Background>
                        </Border>
                        <StackPanel Grid.Column="1" Orientation="Vertical" Margin="0 5 0 0">
                            <TextBlock Text="{Binding Name}" Foreground="Black" FontSize="18" FontWeight="Bold"></TextBlock>
                            <TextBlock Text="{Binding Handle}" Foreground="DarkGray" FontSize="12"/>
                        </StackPanel>
                        <Image Grid.Column="2" Source="Assets/ActionIcons/logo_blue_32.png" Width="32" VerticalAlignment="Top"></Image>
                    </Grid>
                </StackPanel>
                <StackPanel  Grid.Row="1" Margin="14.5,0,0,0" Height="Auto">
                    <StackPanel Name="TweetContent" Tag="{Binding ID}" Margin="15 0 15 0" Tapped="Content_Tapped">
                        <TextBlock Text ="{Binding Content}" TextWrapping="Wrap" Foreground="Black" FontSize="14" Margin="0 0 0 10"/>
                        <ItemsControl  ItemsSource="{Binding ContentImages}">
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <Image Source="{Binding }" MaxWidth="350" Margin="0 0 0 5"  HorizontalAlignment="Center"></Image>
                                    </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                        <TextBlock Foreground="DarkGray" Text="{Binding DateSend}" FontSize="10"></TextBlock>
                    </StackPanel>
                    <StackPanel Name="ActionButtons">
                        <Grid Tag="{Binding ID}" Width="380" Height="25" Margin="0 0 0 10">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>

                            <Button Grid.Column="0" HorizontalAlignment="Center" Margin="20 0 0 0" Style="{StaticResource replyActionButton}" Tapped="Reply_Tapped"></Button>

                            <ToggleButton Grid.Column="2" HorizontalAlignment="Center" 
                                          Style="{StaticResource retweetActionButton}" 
                                          Tapped="Retweet_Tapped"></ToggleButton>
                            <TextBlock Grid.Column="3" HorizontalAlignment="Left" Margin="-15 0 0 0" VerticalAlignment="Center" Text="{Binding RetweetCount}" Foreground="DarkGray"/>

                            <ToggleButton Grid.Column="4" HorizontalAlignment="Center" 
                                          Style="{StaticResource likeActionButton}" 
                                          IsChecked="{Binding LikeState}"  
                                          Tapped="Favourite_Tapped"></ToggleButton>
                            <TextBlock Grid.Column="5"  HorizontalAlignment="Left" Margin="-15 0 0 0" VerticalAlignment="Center" Text="{Binding LikeCount}" Foreground="DarkGray"/>
                        </Grid>
                    </StackPanel>
                </StackPanel>
            </Grid>
        </Border>
    </DataTemplate>

And now when I put the template in the app.xaml file I am getting the following compile error

Events cannot be set in the Application class XAML file

This makes sense for me, but how can I do it anyway? Can I pass the different events like a variable or something into the datatemplate?

//UPDATE - SOLUTION WAY2 using the USERCONTROL:

I've made a UserControl out of the code above and implemented it in the ListView.

<ListView Grid.Row="1" Margin="0 0 0 5"       
        x:Name = "standardBox"
        HorizontalAlignment="Center"
        ScrollViewer.VerticalScrollBarVisibility="Auto"
        ContinuumNavigationTransitionInfo.IsEntranceElement="True">
    <ListView.ItemTemplate>
        <DataTemplate>
            <local:UCGlobal></local:UCGlobal>
        </DataTemplate>
    </ListView.ItemTemplate>
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel VerticalAlignment="Bottom"/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
</ListView>

You could use a few alternatives:

  1. Use the command property of the buttons inside your templates (take care that your DataContext is set correct, to avoid binding errors):

     <DataTemplate x:Key="MyTemplate"> <StackPanel> <Button x:Name="button1" Content="Button1" Command="{Binding Btn1Command}" CommandParameter="{Binding ElementName=button1}"/> <Button x:Name="button2" Content="Button2" Command="{Binding Btn2Command}" CommandParameter="{Binding ElementName=button2}"/> <Button x:Name="button3" Content="Button3" Command="{Binding Btn3Command}" CommandParameter="{Binding ElementName=button3}"/> </StackPanel> </DataTemplate> 

If it´s another type of event that won't call the command you could use InvokeCommandAction which will be handled same as shown in the next example.

  1. Use a trigger like CallMethodAction (same as above. The DataContext is the place where the method will be searched for.):

     <DataTemplate x:Key="MyTemplate"> <StackPanel> <Button x:Name="button1" Content="Button1" > <i:Interaction.Triggers> <i:EventTrigger EventName="Tapped"> <ei:CallMethodAction MethodName="button1_Tapped"/> </i:EventTrigger> </i:Interaction.Triggers> </Button>... 
  2. Write a small UserControl as the base for your DataTemplate :

XAML:

<UserControl x:Class="ThreeBtnUserCtrl"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:local="clr-namespace:DataTemplateIssue"
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300">
    <StackPanel>
       <Button x:Name="button1" Content="Button" Click="button1_Click"/>
       <Button x:Name="button2" Content="Button" Click="button2_Click"/>
       <Button x:Name="button3" Content="Button" Click="button3_Click"/>
    </StackPanel>
</UserControl>

Code behind:

public partial class ThreeBtnUserCtrl : UserControl
{
    public ThreeBtnUserCtrl()
    {
        InitializeComponent();
    }


    private void button1_Click(object sender, RoutedEventArgs e)
    {
        //...some code only controlling view related stuff of your UserCtrl
    }

    private void button2_Click(object sender, RoutedEventArgs e)
    {
        //...some code only controlling view related stuff of your UserCtrl
    }

    private void button3_Click(object sender, RoutedEventArgs e)
    {
        //...some code only controlling view related stuff of your UserCtrl
    }
}

Use it inside your DataTemplate :

<DataTemplate x:Key="MyTemplate">
    <Grid>
        <local:ThreeBtnUserCtrl/>
    </Grid>
</DataTemplate>

You can use a Command and EventTrigger and have it bound to your View Model's command.

<i:Interaction.Triggers>
    <i:EventTrigger EventName="Tapped">
        <i:InvokeCommandAction Command="{Binding TappedCommand}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

Or use a small UserControl insted a DataTemplate :

<UserControl... >
    <StackPanel>
       <Button x:Name="button1" Content="Button" Click="button1_Click"/>
    </StackPanel>
</UserControl>

And use it in your app.xaml:

<DataTemplate x:Key="Template">
    <Grid>
        <local:myUserControl/>
    </Grid>
</DataTemplate>

Use Behaviours in stackpanel

<DataTemplate x:Key="GlobalBox">
    <Border Background="#FFFFFFFF" Margin="10 0 0 5" CornerRadius="2 2 15 2">
        <Grid Width="380">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <StackPanel Grid.Row="0" Tag="{Binding ID}" Name="ProfileInfo" Orientation="Horizontal" Margin="15 15 15 0">
                <Grid Width="360" Margin="0 0 0 10">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="75"></ColumnDefinition>
                        <ColumnDefinition Width="*"></ColumnDefinition>
                        <ColumnDefinition Width="50"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <Border Grid.Column="0" Height="45" Width="45" CornerRadius="5">
                        <Border.Background>
                            <ImageBrush ImageSource="{Binding ImagePath}" Stretch="UniformToFill"/>
                        </Border.Background>
                    </Border>
                    <StackPanel Grid.Column="1" Orientation="Vertical" Margin="0 5 0 0">
                        <TextBlock Text="{Binding Name}" Foreground="Black" FontSize="18" FontWeight="Bold"></TextBlock>
                        <TextBlock Text="{Binding Handle}" Foreground="DarkGray" FontSize="12"/>
                    </StackPanel>
                    <Image Grid.Column="2" Source="Assets/ActionIcons/logo_blue_32.png" Width="32" VerticalAlignment="Top"></Image>
                </Grid>
                <interact:Interaction.Behaviors>
                    <interactcore:EventTriggerBehavior EventName="Tapped" >
                        <interactcore:InvokeCommandAction Command="{Binding Path=DataContext.Btn1Command}" />
                    </interactcore:EventTriggerBehavior>
                </interact:Interaction.Behaviors>
            </StackPanel>

        </Grid>
    </Border>
</DataTemplate>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM