| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

「UWP テンプレート」の版間の差分

提供: MyMemoWiki
ナビゲーションに移動 検索に移動
(ページの作成:「==UWP テンプレート== [Universal Windows Platform][Visual Studio][C#][WPF] *以下のKindle本を参考に自分なりにメモ *非常にわかりやすい上…」)
 
 
(同じ利用者による、間の3版が非表示)
1行目: 1行目:
==UWP テンプレート==
+
==[[UWP テンプレート]]==
[Universal Windows Platform][Visual Studio][C#][WPF]
+
[[Universal Windows Platform]] | [[Visual Studio]] | [[C Sharp]] | [[WPF]] |
  
*以下のKindle本を参考に自分なりにメモ
+
*以下の[[Kindle]]本を参考に自分なりにメモ
 
*非常にわかりやすい上に安い
 
*非常にわかりやすい上に安い
 
{{amazon|B015V7Q4WO}}
 
{{amazon|B015V7Q4WO}}
18行目: 18行目:
 
         // ナビゲーション コンテキストとして動作するフレームを作成し、最初のページに移動します
 
         // ナビゲーション コンテキストとして動作するフレームを作成し、最初のページに移動します
 
         rootFrame = new Frame();
 
         rootFrame = new Frame();
         rootFrame.NavigationFailed += OnNavigationFailed;
+
         rootFrame.Na[[vi]]gationFailed += OnNa[[vi]]gationFailed;
         if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
+
         if (e.Pre[[vi]]ousExecutionState == ApplicationExecutionState.Terminated)
 
         {
 
         {
 
             //TODO: 以前中断したアプリケーションから状態を読み込みます
 
             //TODO: 以前中断したアプリケーションから状態を読み込みます
31行目: 31行目:
 
         // このとき、必要な情報をナビゲーション パラメーターとして渡して、新しいページを
 
         // このとき、必要な情報をナビゲーション パラメーターとして渡して、新しいページを
 
         //構成します
 
         //構成します
         rootFrame.Navigate(typeof(MainPage), e.Arguments);
+
         rootFrame.Na[[vi]]gate(typeof(MainPage), e.Arguments);
 
     }
 
     }
 
     // 現在のウィンドウがアクティブであることを確認します
 
     // 現在のウィンドウがアクティブであることを確認します
62行目: 62行目:
 
     public event PropertyChangedEventHandler PropertyChanged;
 
     public event PropertyChangedEventHandler PropertyChanged;
 
   
 
   
     protected virtual bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
+
     protected virtual bool SetProperty&lt;T&gt;(ref T field, T value, [CallerMemberName] string propertyName = null)
 
     {
 
     {
 
         if (Equals(field, value))
 
         if (Equals(field, value))
69行目: 69行目:
 
         }
 
         }
 
         field = value;
 
         field = value;
         this.RaisePropertyChanged(propertyName);
+
         this.[[R]]aisePropertyChanged(propertyName);
 
         return true;
 
         return true;
 
     }
 
     }
80行目: 80行目:
 
===ICommand===
 
===ICommand===
 
*http://sourcechord.hatenablog.com/entry/2015/08/26/002740
 
*http://sourcechord.hatenablog.com/entry/2015/08/26/002740
  public class RelayCommand : ICommand
+
  public class [[R]]elayCommand : ICommand
 
  {
 
  {
 
     private readonly Action _execute;
 
     private readonly Action _execute;
     private readonly Func<bool> _canexecute;
+
     private readonly Func&lt;bool&gt; _canexecute;
 
   
 
   
 
     public event EventHandler CanExecuteChanged;
 
     public event EventHandler CanExecuteChanged;
 
   
 
   
     public RelayCommand(Action execute) : this(execute, null)
+
     public [[R]]elayCommand(Action execute) : this(execute, null)
 
     {
 
     {
 
     }
 
     }
 
      
 
      
     public RelayCommand(Action execute, Func<bool> canExecute)
+
     public [[R]]elayCommand(Action execute, Func&lt;bool&gt; canExecute)
 
     {
 
     {
 
         if (execute == null)
 
         if (execute == null)
111行目: 111行目:
 
     }
 
     }
 
   
 
   
     public void RaiseCanExecuteChanged()
+
     public void [[R]]aiseCanExecuteChanged()
 
     {
 
     {
 
         CanExecuteChanged?.Invoke(this, EventArgs.Empty);
 
         CanExecuteChanged?.Invoke(this, EventArgs.Empty);
117行目: 117行目:
 
  }
 
  }
 
   
 
   
  public class RelayCommand<T> : ICommand
+
  public class [[R]]elayCommand&lt;T&gt; : ICommand
 
  {
 
  {
     private readonly Action<T> _execute;
+
     private readonly Action&lt;T&gt; _execute;
     private readonly Func<T, bool> _canExecute;
+
     private readonly Func&lt;T, bool&gt; _canExecute;
 
   
 
   
 
     public event EventHandler CanExecuteChanged;
 
     public event EventHandler CanExecuteChanged;
 
   
 
   
     public RelayCommand(Action<T> execute) : this(execute,null)
+
     public [[R]]elayCommand(Action&lt;T&gt; execute) : this(execute,null)
 
     {
 
     {
 
     }
 
     }
 
   
 
   
     public RelayCommand(Action<T> execute, Func<T,bool> canExecute)
+
     public [[R]]elayCommand(Action&lt;T&gt; execute, Func&lt;T,bool&gt; canExecute)
 
     {
 
     {
 
         if (execute == null)
 
         if (execute == null)
148行目: 148行目:
 
     }
 
     }
 
   
 
   
     public void RaiseCanExecuteChanged()
+
     public void [[R]]aiseCanExecuteChanged()
 
     {
 
     {
 
         CanExecuteChanged?.Invoke(this, EventArgs.Empty);
 
         CanExecuteChanged?.Invoke(this, EventArgs.Empty);
156行目: 156行目:
 
===レイアウト===
 
===レイアウト===
 
=====ナビゲーション=====
 
=====ナビゲーション=====
*https://msdn.microsoft.com/windows/uwp/layout/navigation-basics
+
*https://msdn.microsoft.com/windows/uwp/layout/na[[vi]]gation-basics
 
=====レイアウト=====
 
=====レイアウト=====
 
*https://msdn.microsoft.com/windows/uwp/layout/layouts-with-xaml
 
*https://msdn.microsoft.com/windows/uwp/layout/layouts-with-xaml
165行目: 165行目:
 
====/Views/MainPage.xaml====
 
====/Views/MainPage.xaml====
 
*MainPage内のFrameにアクセスする必要があるため、Frameをpublicで公開
 
*MainPage内のFrameにアクセスする必要があるため、Frameをpublicで公開
  <Page
+
  &lt;Page
 
     x:Class="WakeUpOnLan.Views.MainPage"
 
     x:Class="WakeUpOnLan.Views.MainPage"
 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
172行目: 172行目:
 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     mc:Ignorable="d">
+
     mc:Ignorable="d"&gt;
 
   
 
   
     <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
+
     &lt;Grid Background="{Theme[[R]]esource ApplicationPageBackgroundThemeBrush}"&gt;
         <SplitView>
+
         &lt;SplitView&gt;
             <SplitView.Pane>
+
             &lt;SplitView.Pane&gt;
                 <!-- Menu -->
+
                 &lt;!-- [[Menu]] --&gt;
                 <ListView></ListView>
+
                 &lt;ListView&gt;&lt;/ListView&gt;
             </SplitView.Pane>
+
             &lt;/SplitView.Pane&gt;
             <!-- Contents -->
+
             &lt;!-- Contents --&gt;
             <Frame x:Name="RootRrame" x:FieldModifier="public" />
+
             &lt;Frame x:Name="[[R]]oot[[R]]rame" x:FieldModifier="public" /&gt;
         </SplitView>
+
         &lt;/SplitView&gt;
     </Grid>
+
     &lt;/Grid&gt;
  </Page>
+
  &lt;/Page&gt;
 
====/App.xaml.cs====
 
====/App.xaml.cs====
 
*App.OnLaunched()
 
*App.OnLaunched()
198行目: 198行目:
 
         mainPage = new MainPage();
 
         mainPage = new MainPage();
 
   
 
   
         mainPage.RootRrame.NavigationFailed += OnNavigationFailed;
+
         mainPage.RootRrame.Na[[vi]]gationFailed += OnNa[[vi]]gationFailed;
 
   
 
   
         if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
+
         if (e.Pre[[vi]]ousExecutionState == ApplicationExecutionState.Terminated)
 
         {
 
         {
 
             //TODO: 以前中断したアプリケーションから状態を読み込みます
 
             //TODO: 以前中断したアプリケーションから状態を読み込みます
209行目: 209行目:
 
     }
 
     }
 
   
 
   
     if (mainPage.RootRrame.Content == null)
+
     if (mainPage.[[R]]oot[[R]]rame.Content == null)
 
     {
 
     {
 
         // TODO:初期画面に遷移
 
         // TODO:初期画面に遷移
221行目: 221行目:
  
 
====ハンバーガーボタン(/Views/MainPage.xaml)====
 
====ハンバーガーボタン(/Views/MainPage.xaml)====
*StaticResource から取得できる、SymbolThemeFontFamily の E700に定義されている。
+
*Static[[R]]esource から取得できる、SymbolThemeFontFamily の E700に定義されている。
  <Page
+
  &lt;Page
 
     x:Class="WakeUpOnLan.Views.MainPage"
 
     x:Class="WakeUpOnLan.Views.MainPage"
 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
229行目: 229行目:
 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     mc:Ignorable="d">
+
     mc:Ignorable="d"&gt;
 
   
 
   
     <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
+
     &lt;Grid Background="{Theme[[R]]esource ApplicationPageBackgroundThemeBrush}"&gt;
         <Grid.RowDefinitions>
+
         &lt;Grid.[[R]]owDefinitions&gt;
             <RowDefinition Height="Auto"/>
+
             &lt;[[R]]owDefinition Height="Auto"/&gt;
             <RowDefinition/>
+
             &lt;[[R]]owDefinition/&gt;
         </Grid.RowDefinitions>
+
         &lt;/Grid.[[R]]owDefinitions&gt;
         <StackPanel Orientation="Horizontal">
+
         &lt;StackPanel Orientation="Horizontal"&gt;
             <ToggleButton Content="&#xE700;"  
+
             &lt;ToggleButton Content="&#xE700;"  
                           FontFamily="{StaticResource SymbolThemeFontFamily}"
+
                           FontFamily="{Static[[R]]esource SymbolThemeFontFamily}"
 
                           IsChecked="{Binding IsPaneOpen,ElementName=SplitView, Mode=TwoWay}"
 
                           IsChecked="{Binding IsPaneOpen,ElementName=SplitView, Mode=TwoWay}"
 
                           Width="48"
 
                           Width="48"
                           Height="40"/>
+
                           Height="40"/&gt;
         </StackPanel>
+
         &lt;/StackPanel&gt;
         <SplitView x:Name="SplitView" Grid.Row="1">
+
         &lt;SplitView x:Name="SplitView" Grid.[[R]]ow="1"&gt;
             <SplitView.Pane>
+
             &lt;SplitView.Pane&gt;
                 <!-- Menu -->
+
                 &lt;!-- [[Menu]] --&gt;
                 <ListView ItemsSource="{x:Bind ViewModel.HostProfiles}">
+
                 &lt;ListView ItemsSource="{x:Bind ViewModel.Host[[Profile]]s}"&gt;
                 </ListView>
+
                 &lt;/ListView&gt;
             </SplitView.Pane>
+
             &lt;/SplitView.Pane&gt;
             <!-- Contents -->
+
             &lt;!-- Contents --&gt;
             <Frame x:Name="RootRrame" x:FieldModifier="public" />
+
             &lt;Frame x:Name="[[R]]oot[[R]]rame" x:FieldModifier="public" /&gt;
         </SplitView>
+
         &lt;/SplitView&gt;
     </Grid>
+
     &lt;/Grid&gt;
  </Page>
+
  &lt;/Page&gt;
  
 
[[File:1269_uwp_mvvm_hambager_menu.jpg]]
 
[[File:1269_uwp_mvvm_hambager_menu.jpg]]
259行目: 259行目:
 
====={x:Bind} マークアップ拡張=====
 
====={x:Bind} マークアップ拡張=====
 
*https://msdn.microsoft.com/ja-jp/library/windows/apps/mt204783.aspx
 
*https://msdn.microsoft.com/ja-jp/library/windows/apps/mt204783.aspx
*Windows 10 では、{Binding} に代わり、{x:Bind} マークアップ拡張が新たに提供されています。{x:Bind} では、{Binding} の機能のいくつかが省略されていますが、{Binding} よりも短い時間および少ないメモリで動作し、より適切なデバッグをサポートしています。
+
*[[Windows]] 10 では、{Binding} に代わり、{x:Bind} マークアップ拡張が新たに提供されています。{x:Bind} では、{Binding} の機能のいくつかが省略されていますが、{Binding} よりも短い時間および少ないメモリで動作し、より適切なデバッグをサポートしています。
*WPF データ
+
*[[WPF データ]]

2020年2月16日 (日) 04:33時点における最新版

UWP テンプレート

Universal Windows Platform | Visual Studio | C Sharp | WPF |

  • 以下のKindle本を参考に自分なりにメモ
  • 非常にわかりやすい上に安い

MVVM プロジェクトの構成

エントリーポイント(App.xaml,App.xaml.cs)

  • App.xaml.cs が重要な起動処理となる

OnLaunchメソッド

protected override void OnLaunched(LaunchActivatedEventArgs e)
{
    Frame rootFrame = Window.Current.Content as Frame;
    // ウィンドウに既にコンテンツが表示されている場合は、アプリケーションの初期化を繰り返さずに、
    // ウィンドウがアクティブであることだけを確認してください
    if (rootFrame == null)
    {
        // ナビゲーション コンテキストとして動作するフレームを作成し、最初のページに移動します
        rootFrame = new Frame();
        rootFrame.NavigationFailed += OnNavigationFailed;
        if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
        {
            //TODO: 以前中断したアプリケーションから状態を読み込みます
        }
        // フレームを現在のウィンドウに配置します
        Window.Current.Content = rootFrame;
    }
    if (rootFrame.Content == null)
    {
        // ナビゲーション スタックが復元されない場合は、最初のページに移動します。
        // このとき、必要な情報をナビゲーション パラメーターとして渡して、新しいページを
        //構成します
        rootFrame.Navigate(typeof(MainPage), e.Arguments);
    }
    // 現在のウィンドウがアクティブであることを確認します
    Window.Current.Activate();
}
  • アプリケーション通常起動時のエントリーポイント
Window.Current.Content
  • メインウィンドウに表示されるコンテンツ
  • Window.Current.Content に Frameが設定されているか確認。されていなければ、Frameを生成し設定する。
Frame.Content
  • Frame.Content をチェックして何もなければ、MainPageに画面遷移


フォルダ構成

  • 以下のフォルダを作成
  1. Commons
  2. Models
  3. ViewModels
  4. Views

MainPage.xaml

  • デフォルトで作成されている MainPage.xaml を削除
  • Views フォルダに、MainPage.xamlを作成(空白のページを追加)

INotifyPropertyChanged

  • MVVMアプリを作成するためには、INotifyPropertyChanged の実装が必須となる。
  • 一般的には、以下のような基本クラスを作成し、実装負荷を下げる。
public class BindableBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        if (Equals(field, value))
        {
            return false;
        }
        field = value;
        this.RaisePropertyChanged(propertyName);
        return true;
    }

    protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

ICommand

public class RelayCommand : ICommand
{
    private readonly Action _execute;
    private readonly Func<bool> _canexecute;

    public event EventHandler CanExecuteChanged;

    public RelayCommand(Action execute) : this(execute, null)
    {
    }
    
    public RelayCommand(Action execute, Func<bool> canExecute)
    {
        if (execute == null)
        {
            throw new ArgumentNullException("execute");
        }
        _execute = execute;
        _canexecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return (_canexecute == null) ? true : _canexecute();
    }

    public void Execute(object parameter)
    {
        _execute();
    }

    public void RaiseCanExecuteChanged()
    {
        CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }
}

public class RelayCommand<T> : ICommand
{
    private readonly Action<T> _execute;
    private readonly Func<T, bool> _canExecute;

    public event EventHandler CanExecuteChanged;

    public RelayCommand(Action<T> execute) : this(execute,null)
    {
    }

    public RelayCommand(Action<T> execute, Func<T,bool> canExecute)
    {
        if (execute == null)
        {
            throw new ArgumentNullException("execute");
        }
        _execute = execute;
        _canExecute = canExecute;
    }
    
    public bool CanExecute(object parameter)
    {
        return (_canExecute == null) ? true : _canExecute((T)parameter);
    }

    public void Execute(object parameter)
    {
        _execute((T)parameter);
    }

    public void RaiseCanExecuteChanged()
    {
        CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }
}

アプリケーション構成

レイアウト

ナビゲーション
レイアウト
既定のコントロール スタイルとテンプレート

SplitView

  • SplitViewコントロールのPaneにメニューを配置し、Content部分にFrameを配置し画面遷移を行う形が一般的

/Views/MainPage.xaml

  • MainPage内のFrameにアクセスする必要があるため、Frameをpublicで公開
<Page
    x:Class="WakeUpOnLan.Views.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WakeUpOnLan.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <SplitView>
            <SplitView.Pane>
                <!-- Menu -->
                <ListView></ListView>
            </SplitView.Pane>
            <!-- Contents -->
            <Frame x:Name="RootRrame" x:FieldModifier="public" />
        </SplitView>
    </Grid>
</Page>

/App.xaml.cs

  • App.OnLaunched()
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
   var mainPage = Window.Current.Content as MainPage;
   
   // ウィンドウに既にコンテンツが表示されている場合は、アプリケーションの初期化を繰り返さずに、
   // ウィンドウがアクティブであることだけを確認してください
   if (mainPage == null)
   {
       // ナビゲーション コンテキストとして動作するフレームを作成し、最初のページに移動します
       mainPage = new MainPage();

       mainPage.RootRrame.NavigationFailed += OnNavigationFailed;

       if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
       {
           //TODO: 以前中断したアプリケーションから状態を読み込みます
       }

       // フレームを現在のウィンドウに配置します
       Window.Current.Content = mainPage;
   }

   if (mainPage.RootRrame.Content == null)
   {
       // TODO:初期画面に遷移
   }
   // 現在のウィンドウがアクティブであることを確認します
   Window.Current.Activate();

}

真っ白い画面が表示されることを確認

1270 uwp mvvm mainpage.jpg


ハンバーガーボタン(/Views/MainPage.xaml)

  • StaticResource から取得できる、SymbolThemeFontFamily の E700に定義されている。
<Page
    x:Class="WakeUpOnLan.Views.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WakeUpOnLan.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal">
            <ToggleButton Content="" 
                          FontFamily="{StaticResource SymbolThemeFontFamily}"
                          IsChecked="{Binding IsPaneOpen,ElementName=SplitView, Mode=TwoWay}"
                          Width="48"
                          Height="40"/>
        </StackPanel>
        <SplitView x:Name="SplitView" Grid.Row="1">
            <SplitView.Pane>
                <!-- Menu -->
                <ListView ItemsSource="{x:Bind ViewModel.HostProfiles}">
                </ListView>
            </SplitView.Pane>
            <!-- Contents -->
            <Frame x:Name="RootRrame" x:FieldModifier="public" />
        </SplitView>
    </Grid>
</Page>

1269 uwp mvvm hambager menu.jpg

{x:Bind} マークアップ拡張