デモ デモ:

あなたの時間は貴重です。長ったらしい文章を読みたくない方は、最後までスクロールしてソースコードをダウンロードしてください!
1. 新しいプロジェクトの作成
サイト管理者の開発環境:
- VS 2019 Enterprise 16.70
- .NET 5 Preview 5
.NET 5 WPF プロジェクトテンプレートと .NET Core 3.1 WPF プロジェクトテンプレートに違いはありません。プロジェクトを作成したら、NuGet で MaterialDesignThemes ライブラリを導入します:

2. スタイルの導入
デモは 1 つの xaml ファイルと xaml.cs ファイルのみです。後で WPF の UI デザイン効果を収集しやすくするため、オープンソースプロジェクト TerminalMACS.ManagerForWPF に統一して配置しています。そのため、コントロールのスタイル参照は FoodAppLoginView.xaml に直接追加します:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.Amber.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
3. コントロールのアニメーション効果
上の GIF アニメーションの通り、ログインウィンドウ読み込み時に、ユーザー名入力ボックス、パスワード入力ボックス、パスワードを記憶、右側の背景画像などの要素にアニメーション効果があります。各部分のコード構造は似ており、例えば以下のユーザー名入力ボックスのコード:
<!--#region User name textblox-->
<materialDesign:TransitioningContent Grid.Row="2" Margin="90,20,00,0" HorizontalAlignment="Left">
<materialDesign:TransitioningContent.OpeningEffects>
<materialDesign:TransitionEffect Kind="SlideInFromLeft" Duration="0:0:2"/>
</materialDesign:TransitioningContent.OpeningEffects>
<StackPanel Style="{StaticResource setVisibilityBasedLogin}" Orientation="Horizontal">
<materialDesign:PackIcon Kind="Account" Width="16" Height="16" VerticalAlignment="Center"
Margin="0,5,10,0" Foreground="{Binding ElementName=NameTextBox, Path=BorderBrush}"/>
<TextBox x:Name="NameTextBox" Width="140" materialDesign:HintAssist.Hint="{markup:I18n {x:Static i18NResources:Language.FoodAppLoginView_UserName}}"
Style="{StaticResource MaterialDesignFloatingHintTextBox}"/>
</StackPanel>
</materialDesign:TransitioningContent>
<!--#endregion-->
オープンソースコントロール MD の TransitioningContent コンポーネントを使用しています。TransitionEffect の Kind プロパティでコントロールのアニメーション方向を設定します。
4. ログインのシミュレーション
ログインボタンのレイアウトコード:
<!--#region control panel-->
<materialDesign:TransitioningContent Grid.Row="4" Margin="40,20,0,0">
<materialDesign:TransitioningContent.OpeningEffects>
<materialDesign:TransitionEffect Kind="SlideInFromBottom" Duration="0:0:2"/>
</materialDesign:TransitioningContent.OpeningEffects>
<StackPanel Style="{StaticResource setVisibilityBasedLogin}" Orientation="Horizontal" HorizontalAlignment="Center">
<CheckBox Content="{markup:I18n {x:Static i18NResources:Language.FoodAppLoginView_RememberMe}}"/>
<Button Style="{StaticResource MaterialDesignRaisedButton}"
Command="{x:Static materialDesign:DialogHost.OpenDialogCommand}"
materialDesign:ButtonAssist.CornerRadius="20"
Width="80" Height="40" Margin="120,0,0,0"
Content="{markup:I18n {x:Static i18NResources:Language.FoodAppLoginView_Login}}"/>
</StackPanel>
</materialDesign:TransitioningContent>
<!--#endregion-->
ログインボタンをクリックすると、待機ダイアログが開きます(クリック時に materialDesign:DialogHost.OpenDialogCommand がバインドされています)。待機ダイアログのオープン/クローズイベントでログイン処理を行います。
private async Task<bool> ValidateCreds()
{
// ログインをシミュレート
// サーバーにログイン情報を送信し、認証結果を受け取ることができます
await Task.Delay(TimeSpan.FromSeconds(2));
Random gen = new Random(DateTime.Now.Millisecond);
int loginProb = gen.Next(100);
return loginProb <= 20;
}
private async void OpenCB_DialogOpened(object sender, MaterialDesignThemes.Wpf.DialogOpenedEventArgs eventArgs)
{
try
{
this.IsJustStarted = true;
this.LoginStatusmsg = "";
bool isLoggedIn = await ValidateCreds();
if (isLoggedIn)
{
// ログインダイアログを閉じてメインウィンドウを表示する必要があります
eventArgs.Session.Close(true);
}
else
{
// ログイン失敗、パラメータとしてfalseを設定
eventArgs.Session.Close(false);
}
}
catch (Exception)
{
//throw;
}
}
private void ClosingCB_DialogClosing(object sender, MaterialDesignThemes.Wpf.DialogClosingEventArgs eventArgs)
{
if (eventArgs.Parameter == null)
{
return;
}
IsLoggedIn = (bool)eventArgs.Parameter;
IsJustStarted = false;
if(IsLoggedIn)
{
this.LoginStatusmsg = I18nManager.Instance.Get(I18nResources.Language.FoodAppLoginView_Success).ToString();
}
else
{
this.LoginStatusmsg = I18nManager.Instance.Get(I18nResources.Language.FoodAppLoginView_Fail).ToString();
}
}
待機ダイアログのオープンイベント内でログイン処理をシミュレートしています。
待機ダイアログのクローズイベント内で UI の応答メッセージを表示します。
5. ソースコードのダウンロード
上記では主要なコードの一部のみを掲載しています。ソースコードは GitHub に公開しています。