2017-02-28 8 views
0

増加するパラメータに従って、内部を色で塗りつぶすコンテナを作成します。 メインウィンドウ:値に応じて高さを変更する

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="350" Width="525"> 
<Grid> 
    <Border BorderBrush="Black" BorderThickness="1" Width="100" Height="200"> 
     <Rectangle VerticalAlignment="Bottom" Height="{Binding Height}" Width="100" Fill="Red" MaxHeight="200"/> 
    </Border> 
</Grid> 

Engine.cs:

class Engine 
{ 
    public ViewModel viewModel = new ViewModel(); 

    public void process() 
    { 
     Thread a = new Thread(() => 
     { 
      while (viewModel.Height < 200) 
      { 
       ChangeHeight(); 
       Thread.Sleep(1000); 
      } 
     }); 
     a.IsBackground = true; 
     a.Start(); 

    } 
    public void ChangeHeight() 
    { 
     viewModel.Height++;    
    } 
} 

のViewModelがDataContextのである例えば

iは、次の例を作成しました。それは素晴らしい作品ですが、私がやったよりもはるかに優れたものがあると思います。 さらに、ここではアニメーションが必要であることを意味する滑らかなものとしてChangeHeight()の転送が必要です。

良い例や指針はありますか?

UPDATE 私は、ビューモデルのコードを追加している:

namespace WpfApplication1 

{ パブリッククラスのViewModel:m_height = 0 { プライベートint型をINotifyPropertyChangedの。 public int高さ { get {return m_height; } セット { m_height = value; NotifyPropertyChanged( "Height"); }}

#region "PropertyChanged Event" 
    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    #endregion 
} 

は}

+0

ViewModelに 'INotifyPropertyChanged'を実装しましたか?そのコードを質問に追加できますか? – CKII

+0

なぜあなたはそれが滑らかではないと感じますか?ここで何が起きてるの。詳細を追加できますか? – Versatile

+0

参照:http://stackoverflow.com/questions/3762576/wpf-backgroundworker-vs-dispatcher – Versatile

答えて

1

代わりに、プログラムビューモデルのプロパティをアニメーション化するには、例えばのようなターゲットプロパティをアニメーション化ビュー内の添付プロパティを有していてもよいですHeight

public static class Animated 
{ 
    private static Duration duration = TimeSpan.FromSeconds(5); 

    public static readonly DependencyProperty HeightProperty = 
     DependencyProperty.RegisterAttached(
      "Height", typeof(double), typeof(Animated), 
      new PropertyMetadata(HeightPropertyChanged)); 

    public static double GetHeight(DependencyObject obj) 
    { 
     return (double)obj.GetValue(HeightProperty); 
    } 

    public static void SetHeight(DependencyObject obj, double value) 
    { 
     obj.SetValue(HeightProperty, value); 
    } 

    private static void HeightPropertyChanged(
     DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     var element = obj as FrameworkElement; 

     if (element != null) 
     { 
      var to = (double)e.NewValue; 
      var animation = double.IsNaN(element.Height) 
       ? new DoubleAnimation(0, to, duration) 
       : new DoubleAnimation(to, duration); 

      element.BeginAnimation(FrameworkElement.HeightProperty, animation); 
     } 
    } 
} 

あなたはこのようにXAMLでそれを使用します。

<Rectangle Fill="Red" Width="100" Height="0" 
    local:Animated.Height="{Binding TargetHeight}"/> 

、ちょうど所望の目標値にTargetHeightビューモデルプロパティを設定します。

+0

それは私がちょうど何かを理解したいと思う素晴らしい、私はそれが高さではなく幅Propetyを持つアニメーションを変更しようとしました。どのようにそれを行うことができますか? – Joe

+0

BeginAnimation(別のアタッチされたプロパティのPropertyChangedCallback内)に 'FrameworkElement.WidthProperty'を渡します。アニメーションの持続時間は、XAMLで設定できるように、添付プロパティとして宣言することもできます。 – Clemens

+0

xamlでローカルを追加することはできますか:Animated.Width?私はそれを試みましたが、このプロパティは表示されません – Joe

0

使用純粋なアニメーション

<Border BorderBrush="Black" BorderThickness="1" Width="100" > 
     <Rectangle VerticalAlignment="Bottom" Height="50" Width="100" Fill="Red" > 
      <Rectangle.Triggers> 
       <EventTrigger RoutedEvent="Loaded"> 
        <BeginStoryboard> 
         <Storyboard Storyboard.TargetProperty="Height"> 
          <DoubleAnimation From="0" To="{Binding Height}" Duration="0:0:20"/> 
         </Storyboard> 
        </BeginStoryboard> 
       </EventTrigger> 
      </Rectangle.Triggers> 
     </Rectangle> 
    </Border> 

あなたの現在のアプローチをリファクタリング、使用Taskおよびマルチスレッドプログラムを書くための近代的な方法ですasync/await

private void Button_Click_1(object sender, RoutedEventArgs e) 
    { 
     Task.Factory.StartNew(() => { App.Current.Dispatcher.Invoke(async() => 
      { 
       while (this.Height < 200) 
       { 
        await Task.Delay(1000); 
        ++viewModel.Height; 
       } 
      }); 
     }); 
    } 
関連する問題