Thanh Le
Thanh Le

Reputation: 69

How to add controls dynamic in xaml apps for windows 8

I am making a grid application, and in ItemsDetaiPage.xaml

<common:LayoutAwarePage
x:Name="pageRoot"
x:Class="App6.ItemDetailPage"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App6"
xmlns:data="using:App6.Data"
xmlns:common="using:App6.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Page.Resources>

    <!-- Collection of items displayed by this page -->
    <CollectionViewSource
        x:Name="itemsViewSource"
        Source="{Binding Items}"
        d:Source="{Binding AllGroups[0].Items, Source={d:DesignInstance Type=data:SampleDataSource, IsDesignTimeCreatable=True}}"/>
</Page.Resources>

<!--
    This grid acts as a root panel for the page that defines two rows:
    * Row 0 contains the back button and page title
    * Row 1 contains the rest of the page layout
-->
<Grid
    Style="{StaticResource LayoutRootStyle}"
    DataContext="{Binding Group}"
    d:DataContext="{Binding AllGroups[0], Source={d:DesignInstance Type=data:SampleDataSource, IsDesignTimeCreatable=True}}">

    <Grid.RowDefinitions>
        <RowDefinition Height="140"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <!-- Back button and page title -->
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Button x:Name="backButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResource BackButtonStyle}"/>
        <TextBlock x:Name="pageTitle" Text="{Binding Title}" Style="{StaticResource PageHeaderTextStyle}" Grid.Column="1"/>
    </Grid>

    <!--
        The remainder of the page is one large FlipView that displays details for
        one item at a time, allowing the user to flip through all items in the chosen
        group
    -->
    <FlipView
        x:Name="flipView"
        AutomationProperties.AutomationId="ItemsFlipView"
        AutomationProperties.Name="Item Details"
        TabIndex="1"
        Grid.Row="1"
        Margin="0,-3,0,0"
        ItemsSource="{Binding Source={StaticResource itemsViewSource}}">

        <FlipView.ItemTemplate>
            <DataTemplate>

                <!--
                    UserControl chosen as the templated item because it supports visual state management
                    Loaded/unloaded events explicitly subscribe to view state updates from the page
                -->
                <UserControl Loaded="StartLayoutUpdates" Unloaded="StopLayoutUpdates">
                    <ScrollViewer x:Name="scrollViewer" Style="{StaticResource HorizontalScrollViewerStyle}" Grid.Row="1">

                        <!-- Content is allowed to flow across as many columns as needed -->
                        <Grid Margin="120,0,20,20">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="800"></ColumnDefinition>
                                <ColumnDefinition Width="40"></ColumnDefinition>
                                <ColumnDefinition Width="400"></ColumnDefinition>
                                <ColumnDefinition Width="40"></ColumnDefinition>
                                <ColumnDefinition Width="200"></ColumnDefinition>
                            </Grid.ColumnDefinitions>
                            <StackPanel Orientation="Vertical" Grid.Column="0">
                                <TextBlock FontSize="26.667" FontWeight="Light" Text="{Binding Title}" TextWrapping="Wrap"/>
                                <TextBlock FontSize="26.667" FontWeight="Light" Text="{Binding Date}" TextWrapping="Wrap"/>
                                <WebView x:Name="webView" Width="800" Height="500"/>
                                <StackPanel x:Name="spButton" Orientation="Horizontal">

                                </StackPanel>
                            </StackPanel>
                            <StackPanel Orientation="Vertical" Grid.Column="2">
                                <TextBlock FontSize="26.667" FontWeight="Light" Text="{Binding Description}" TextWrapping="Wrap"/>
                            </StackPanel>
                            <StackPanel Orientation="Vertical" Grid.Column="4">
                                <TextBlock FontSize="26.667" FontWeight="Light" Text="{Binding Tag}" TextWrapping="Wrap"/>
                            </StackPanel>
                        </Grid>
                        <VisualStateManager.VisualStateGroups>

                            <!-- Visual states reflect the application's view state inside the FlipView -->
                            <VisualStateGroup x:Name="ApplicationViewStates">
                                <VisualState x:Name="FullScreenLandscape"/>
                                <VisualState x:Name="Filled"/>

                                <!-- Respect the narrower 100-pixel margin convention for portrait -->
                                <VisualState x:Name="FullScreenPortrait">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="richTextColumns" Storyboard.TargetProperty="Margin">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="97,0,87,57"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="image" Storyboard.TargetProperty="MaxHeight">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="400"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>

                                <!-- When snapped, the content is reformatted and scrolls vertically -->
                                <VisualState x:Name="Snapped">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="richTextColumns" Storyboard.TargetProperty="Margin">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="17,0,17,57"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="scrollViewer" Storyboard.TargetProperty="Style">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource VerticalScrollViewerStyle}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="richTextBlock" Storyboard.TargetProperty="Width">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="280"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="image" Storyboard.TargetProperty="MaxHeight">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="160"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </ScrollViewer>
                </UserControl>
            </DataTemplate>
        </FlipView.ItemTemplate>
    </FlipView>

    <VisualStateManager.VisualStateGroups>

        <!-- Visual states reflect the application's view state -->
        <VisualStateGroup x:Name="ApplicationViewStates">
            <VisualState x:Name="FullScreenLandscape"/>
            <VisualState x:Name="Filled"/>

            <!-- The back button respects the narrower 100-pixel margin convention for portrait -->
            <VisualState x:Name="FullScreenPortrait">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PortraitBackButtonStyle}"/>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>

            <!-- The back button and title have different styles when snapped -->
            <VisualState x:Name="Snapped">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}"/>
                    </ObjectAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}"/>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Grid>

My apps synthesis clips, each items is a game, each games have views, in StackPanel spButton I want to add buttons as a link to play videos. How can add dynamic buttons in file .cs

Upvotes: 0

Views: 1783

Answers (1)

Tilak
Tilak

Reputation: 30698

This is typical case of invoking controls method through View Model.

To accomplish this, You need to following steps
1. Define an interface INavigatable that expose Navigate event
2. Implement the interface in ViewModel.
3. In the View Code behind, check if DataContext implements INavigatable interface.
4. If step 3 is true, Subscribe to View Model event in view code behind.

Example.

Step 1:

class NavigateEventArgs:EventArgs
{
    public string Target {get;set;}
}

public delegate void NavigateEventHandler (object sender, NavigateEventArgs nargs);

public interface INavigatable
{
    event NavigateEventHandler Navigate;
}

Step 2:

class MyViewModel : INavigatable
{
    public event NavigateEventHandler Navigate;

    MyViewModel()
    {
        NavigateCommand = new DelegateCommand(() => 
        {
            RaiseNavigateEvent();
        }) ;
    }

    void RaiseNavigateEvent()
    {
        var temp = Navigate;
        if (temp != null)
        {
            temp(new NavigateEventArgs{Target = Link});
        }
    }

    public string Link {get;set;} // this should be bound to Button.Content (preferably in XAML)
    public ICommand NavigateCommand{ get;set;}
}

Step 3/4:

public class MyView : Window
{
    public MyView()
    {
        ...
        Load += (s,e)=> 
        {
            if (this.DataContext is INavigatable)
            {
                ((INavigatable)(this.DataContext)).Navigate += (s1,e1) => webView.Navigate(e1.Target);
            }
        }

    }
}

As an improvement, subscribe/unsubscribe the Navigate event in DataContextChanged event instead of Load event

Upvotes: 1

Related Questions