プログラムの事とか

お約束ですが「掲載内容は私個人の見解です」

UWPのターゲットバージョンを上げたらプログレスバー(Storyboard?)の動作が変わっちゃった話

あけましておめでとうございます

令和も早くも2年目に突入した今日この頃、いかがお過ごしでしょうか? 私はいつも通り、過去の遺物をいじる作業でございます

今回の題材はUWP 当時の対象OSは「Windows 10 Fall Creators Update(1709)」です 時の経つのは早いもので、このOSはすでにサポート対象外となっております


NuGet Packageの更新とかもろもろやっていたらターゲットバージョンが古くてビルドが通らなくなったので、ターゲットバージョンを上げたらプログレスバー(Storyboard?)の動作が変わっちゃったよ!というお話

準備

新規のUWPアプリを作ります

MainPage.xaml

<Page.Resources>
    <Storyboard x:Name="ValueStoryboard">
        <DoubleAnimation Storyboard.TargetName="ProgressBar1" Storyboard.TargetProperty="Value" EnableDependentAnimation="True" To="100" Duration="00:00:00.5"/>
    </Storyboard>
</Page.Resources>
<Grid Margin="40">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <ProgressBar x:Name="ProgressBar1" Minimum="0" Maximum="10" Height="20"/>
    <Slider Grid.Row="1" x:Name="Slider1" Minimum="0" Maximum="20" Value="0" ValueChanged="Slider1_ValueChanged"/>
    <StackPanel Grid.Row="2" Orientation="Horizontal">
        <TextBlock Text="ProgressBar1.Value = "/>
        <TextBlock Text="{Binding ElementName=ProgressBar1,Path=Value}"/>
    </StackPanel>
    <StackPanel Grid.Row="3" Orientation="Horizontal">
        <TextBlock Text="Slider1.Value = "/>
        <TextBlock Text="{Binding ElementName=Slider1,Path=Value}"/>
    </StackPanel>
</Grid>

MainPage.xaml.cs

private void Slider1_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
    var storyBoard = (Storyboard)this.Resources["ValueStoryboard"];
    ((DoubleAnimation)storyBoard.Children[0]).To = e.NewValue;
    storyBoard.Begin();
}
  • プログレスバーの最大値は10
  • スライダーの最大値は20
  • プログレスバーの値はStoryboard(ValueStoryboard)で変更
  • スライダーの値が変わるとコードビハインド側でその値をToに設定してStoryboardを実行

というものです

TargetPlatformVersion=10.0.16299.0

f:id:puni-o:20200107093844p:plain

まずは1709をターゲットにして試します

f:id:puni-o:20200107094105g:plain

こんな感じ。プログレスバーの最大値が10なのでそれ以上の値にはなりません

TargetPlatformVersion=10.0.17134.0

f:id:puni-o:20200107094345p:plain

次に1803をターゲットにして試します

f:id:puni-o:20200107094450g:plain

はい

プログレスバーの値が最大値を超えます

ちなみに

<ProgressBar x:Name="ProgressBar1" Minimum="0" Maximum="10" Height="20" Value="{Binding ElementName=Slider1,Path=Value}"/>

こんな感じで直接値を入れた場合はちゃんと最大値で止まります

まとめ

1803からこんな感じの動作になったっぽいですね。当時のBreaking changesに書いてあるのかもしれませんが、面倒なので調べていません

それでは、よいお年を

WPFでSystem.Windows.PointがそのままBindingできるのを知らなかった話

.NET Core 3.0で試してます。それ以外は知りません

結論

いつからなのか、ずっとそうなのか、WPFでSystem.Windows.Pointを編集する際にそのままBindingできました

おしまい


以下だらだらと

試してみる

ViewModel

public class MainViewModel
{
    public ReactiveProperty<Point> Point { get; } = new ReactiveProperty<Point>();
    public MainViewModel()
    {
        Point.Subscribe(p => System.Diagnostics.Debug.WriteLine("Update : " + p));
    }
}

これだけ、ReactivePropertyらくちんちん

View (抜粋)

<TextBlock Text="Point"/>
<TextBox Grid.Column="1" Text="{Binding Point.Value}"/>

実行結果

f:id:puni-o:20191009165951p:plain

できた!

フォーマット指定もできるよ

f:id:puni-o:20191009170109p:plain

Validationももろちん

f:id:puni-o:20191009170146p:plain

とりあえず思いつく構造体を並べてみた

f:id:puni-o:20191009170544p:plain

全部いけた!!

まとめ

見た目を凝ろうと思ったらやっぱりこれだと辛い(数値はNumericUpDownを求められたり)んですが、とりあえず設定ができればいいレベルのものならこれでいいじゃない

いままでいちいち要素毎に分けていたよ・・・

ファイルに保存するILoggerの拡張のやつ(?)作りました

github.com

作りました

.NET Core 3.0だしHostBuilderとかあるから、一応ね


以下ぽえむ

私は社会人になってから真面目にプログラミングを行うようになったので、ログの重要性などもそこで教わりました

その時のエース的プログラマーな方が作ったログ用APIはかなり良くできていて、今考えてもすごいものを与えられていたんだなーと思います

  • リアルタイムに出るUIがあって色も付く (今回関係ないね)

  • printfみたいな感じで使える (今回関係ないね)

  • ファイルがサイズでローテーションする (Windows NTで1MByte超えるテキストファイル開くと辛い!)

とか初心者な私はただ関心していました

さて、そんなAPIを使用して出力したログに付き合うこと?年、ファイルに保存するタイプのログはこのAPIライクなものじゃないと体が満足してくれなくなりました。三つ子の魂百までとはよく言ったものです

ETW使ってもファイル保存部分は同じような形式で保存するようにしてましたし、今回コンソールアプリでMicrosoft.Extensions.Loggingを使うことになったのでこいつでも同じですね

皆さんも自分にピッタリくるログファイルの形式があるとおもいます。GitHubのソースはかなり単純だと思うのでこぴって自分だけのログファイルを作ってみてはいかがでしょうか?