

C#でイベントハンドラとして画面から音量を受け取るコードを書きたいと思っています。  
以下の画像にあるようなスライドバーから音量を取得する仕組みにしたいです。  
[![画面](https://i.stack.imgur.com/Wthr0.png)](https://i.stack.imgur.com/Wthr0.png)

スライダーを使って音量を変更するシステムですので、スライダーの値が変更されたら、その値を取得するようにしたいです。

取得した値を別のコンポーネントに出すにはどの様に記述すればよろしいでしょうか？


CC BY-SA 4.0
2020-07-05T06:18:08.347
68292
2020-08-16T12:06:55.670
2020-07-05T20:40:28.467
4236
40923
question
c# wpf
スライダーの値が変更されたら、その値を取得するようにしたい


コメントで紹介した記事などで書かれているでしょう。  
[C#WPFの道#18！Slider（スライダー）の書き方と使い方を解りやすく解説](https://anderson02.com/cs/wpf/wpf-18/)  
[WPF sliderの使い方(スクロールバー的な)](https://www.techlive.tokyo/archives/1166)

Microsoftのページはこちら。  
[Slider クラス](https://docs.microsoft.com/ja-
jp/dotnet/api/system.windows.controls.slider?view=netcore-3.1#events)

  * Sliderコントロールの[ValueChanged(RangeBase.ValueChanged)](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.controls.primitives.rangebase.valuechanged?view=netcore-3.1)イベントにイベントハンドラを登録する  
以下の`ValueChanged="Slider_ValueChanged"`の部分

>
[code]

>     <Slider Width="200"
>             TickPlacement="Both"
>             Foreground="Black"
>             Margin="10"
>             IsSnapToTickEnabled="True"
>             TickFrequency="10"
>             SmallChange="20"
>             LargeChange="50"
>             Minimum="0"
>             Maximum="100"
>             ValueChanged="Slider_ValueChanged"/>
>     <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
>         <TextBlock Text="SliderValue:"/>
>         <TextBlock x:Name="ASlider"/>
>     </StackPanel>
>  
[/code]

  * イベント通知時の[RoutedPropertyChangedEventArgs](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.routedpropertychangedeventargs-1?view=netcore-3.1)パラメータの[NewValue](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.routedpropertychangedeventargs-1.newvalue?view=netcore-3.1#System_Windows_RoutedPropertyChangedEventArgs_1_NewValue)プロパティに新しい値が入っているのでそれを使う。必要ならば変更前の値を[OldValue](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.routedpropertychangedeventargs-1.oldvalue?view=netcore-3.1#System_Windows_RoutedPropertyChangedEventArgs_1_OldValue)プロパティから取得する。  
以下の`ASlider.Text = e.NewValue.ToString();`の部分

>
[code]

>     private void Slider_ValueChanged(object sender,
> RoutedPropertyChangedEventArgs e)
>     {
>         ASlider.Text = e.NewValue.ToString();
>     }
>  
[/code]

  * 読み取るだけならSliderコントロール自身の[Value(RangeBase.Value)](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.controls.primitives.rangebase.value?view=netcore-3.1#System_Windows_Controls_Primitives_RangeBase_Value)プロパティでも良いのかもしれませんが、イベントハンドラの中でその値を書き換えると再度イベントが発生してループになるでしょう。  
上記2つ目記事の以下の`SliderValue.Text = slider.Value.ToString();`の部分

>
[code]

>     private void slider_ValueChanged(object sender,
> RoutedPropertyChangedEventArgs<double> e)
>     {
>         SliderValue.Text = slider.Value.ToString();
>     }
>  
[/code]

* * *

質問の方が更新される前に追記しますが、おそらくイベントハンドラの中から画面(UIコンポーネント)の表示更新を行いたいのでしょう。  
以下のMicrosoftや他の記事にあるように、`Dispatcher`の`BeginInvoke`、`Invoke`、`InvokeAsync`などを使えば良いのでしょう。  
[スレッド モデル](https://docs.microsoft.com/ja-
jp/dotnet/framework/wpf/advanced/threading-model)

> ただし、どれほど適切に設計したとしても、あらゆる種類の問題に対してシングルスレッドのソリューションを UI フレームワークで提供することはできません。
> WPF はもう一歩のところですが、複数のスレッドで ユーザー インターフェイス (UI)
> の応答性またはアプリケーションのパフォーマンスが向上する状況がまだあります。

> **注意**  
>  このトピックでは、非同期呼び出しに BeginInvoke メソッドを使用したスレッド処理について説明します。 また、Action または Func
> をパラメーターとして受け取る InvokeAsync メソッドを呼び出して、非同期呼び出しを行うこともできます。 ...途中省略... Invoke
> メソッドには、Action または Func をパラメーターとして受け取るオーバーロードもあります。...以下省略

[WPF の Dispatcher
について勉強してみた](https://hilapon.hatenadiary.org/entry/20130225/1361779314)

> WPFでは、ほとんどのオブジェクトが UI スレッド上で動作する「シングルスレッドモデル」を採用しているため、UI
> スレッド外からそのオブジェクトにアクセスすると、例外が発生します。  
>  例えば、以下のように ListBox へのアイテム追加を並列実行すると、InvalidOperationException がスローされます。
[code]

>     private void button1_Click(object sender, RoutedEventArgs e) {
>         listBox1.Items.Clear();
>  
>         Parallel.For(0, 10000, (i) => {
>             listBox1.Items.Add(i); // ここで例外
>         });
>     }
>  
[/code]

> Dispatcher.BeginInvoke を使えば非同期に Viewの要素にアクセスできます。
[code]

>     private void button1_Click(object sender, RoutedEventArgs e) {
>         listBox1.Items.Clear();
>  
>         Parallel.For(0, 10000, (i) => {
>             listBox1.Dispatcher.BeginInvoke(
>                  new Action(() => {
>                         listBox1.Items.Add(i);
>                  })
>             );
>         });
>     }
>  
[/code]


CC BY-SA 4.0
2020-07-05T15:18:17.227
68310
2020-07-06T00:57:09.190
2020-07-06T00:57:09.190
26370
26370
68292
answer