2017-03-19 4 views
0

私はアラームアナンシエータを表すカスタムコントロールを作成しようとしています。視覚的に、制御が非常に簡単で、次のようになります。WPFカスタムコントロール(ユーザー設定可能な値間のカラーアニメーションあり)

enter image description here

アナンシエータ制御のための重要な設計基準は次のとおりです。

  • は、制御ライブラリ
  • の一部として出荷することができますシステムのデフォルトとは異なりますが、ユーザが上書きできるデフォルトスタイル(色、フォント)を持っています
  • ユーザが指定できるテキスト(通常は1語、たとえば「ALARM」)があります。
  • アラートの重大度に応じて、テキストはさまざまなリズムの1つで点滅する必要があります。ケイデンスはユーザーによって設定可能です。ケイデンスにはSteadyOnSteadyOffが含まれていますが、いくつかの選択肢があります。
  • アナンシエータがオン/ライトされているときは、ActiveColorプロパティで指定された色でレンダリングされます。
  • アナンシエータがオフのときは、InactiveColorプロパティでレンダリングされます。 InactiveColorは、通常、背景色に近いが、同一ではない。
  • ActiveColorおよびInactiveColorは、ユーザーが設定できます。

私は自分のカスタムコントロールをControlクラスに基づいています。ビジュアルツリーは、基本的には境界線と、このようGeneric.xamlで定義されてTextBlock、から構成されています

<Style TargetType="{x:Type local:Annunciator}"> 
    <Setter Property="FontFamily" Value="OCR A Extended" /> 
    <Setter Property="FontSize" Value="12" /> 
    <Setter Property="BorderThickness" Value="1" /> 
    <Setter Property="BorderBrush" Value="Black" /> 
    <Setter Property="Margin" Value="2" /> 
    <Setter Property="Padding" Value="2" /> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type local:Annunciator}"> 
       <Border Background="{TemplateBinding Background}" 
         BorderBrush="{TemplateBinding BorderBrush}" 
         BorderThickness="{TemplateBinding BorderThickness}"> 
        <TextBlock x:Name="AnnunciatorTextBlock" 
           TextWrapping="Wrap" 
           Text="{TemplateBinding AnnunciatorText}" 
           Foreground="{TemplateBinding ActiveColor}" 
           TextAlignment="Center" 
           /> 
       </Border> 
       </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

は当初、私は、ストーリーボードおよびトリガを使用して作業したアニメーションを取得しようとしました。これは洗練された解決策でしたが、コントロールテンプレートで Toプロパティに {TemplateBinding}を使用できず、 ColorAnimationというプロパティを使用できなかったため、レンガ壁に遭遇しました。何時間も何度も読んだ後、私はこれが実行可能な選択肢ではないと結論づけました(おそらく私は間違っていますか?)。

私はコードビハインドを使用して、数年前にWindowsフォームで行ったのと同じようなコントロールを使って解決しました。その解決策で私はCadencemanagerシングルトンを持っています。コントロールはCadenceManagerに登録され、コントロールを更新する必要があるときはいつでも、CadenceManagerはコントロールのICadencedControl.CadenceUpdate()メソッドを呼び出します。私はDispatcherTimerを使ってこのテクニックを試して、クロススレッドのアップデートの問題とすべてのコードが実行されないようにしました。私のカスタムコントロールの更新方法では、私はそうのようなテキストブロックの前景色を更新:予想通り(デバッガでブレークポイントを設定することによって証明されるように)

public void CadenceUpdate(bool newState) 
     { 
     var brush = newState && IsEnabled && !Muted ? ActiveColor : InactiveColor; 
     textBlockControl.Foreground = brush; 
     } 

更新メソッドが呼び出されています。ただし、テキストの色は決して更新されません。

DispatcherTimerティックイベントに応答して、私のカスタムコントロールの更新で私のTextBlock要素の色をどうやって作るのですか?なぜこれが動作していないのか分かりません。

+0

フォアグラウンド:

あなたは今、このようなvisualSTATEのを有効でしょう。より良い解決策が必要な場合は、トリガーやストーリーボードで失敗した試行を投稿してください。そのまま - 質問はあまり明確ではありません。 – Evk

答えて

1

あなたは別の点滅状態のためVisualStatesを使用することができます。ストーリーボードはInactiveColorActiveColorバインディングがRelativeSource TemplatedParentを動作させるためにリソースとして宣言されていること

<ControlTemplate TargetType="{x:Type local:Annunciator}"> 
    <Border Background="{TemplateBinding Background}" 
      BorderBrush="{TemplateBinding BorderBrush}" 
      BorderThickness="{TemplateBinding BorderThickness}"> 
     <Border.Resources> 
      <Storyboard x:Key="BlinkingStoryboard"> 
       <ColorAnimation 
        Storyboard.TargetName="AnnunciatorTextBlock" 
        Storyboard.TargetProperty="Foreground.Color" 
        From="{Binding InactiveColor, 
          RelativeSource={RelativeSource TemplatedParent}}" 
        To="{Binding ActiveColor, 
         RelativeSource={RelativeSource TemplatedParent}}" 
        Duration="0:0:1" 
        AutoReverse="True" 
        RepeatBehavior="Forever"/> 
      </Storyboard> 
      <!-- more Storyboards --> 
     </Border.Resources> 
     <VisualStateManager.VisualStateGroups> 
      <VisualStateGroup Name="FlashStates"> 
       <VisualState Name="Blinking" 
          Storyboard="{StaticResource BlinkingStoryboard}"/> 
       <!-- more VisualStates --> 
      </VisualStateGroup> 
     </VisualStateManager.VisualStateGroups> 
     <TextBlock x:Name="AnnunciatorTextBlock" Text="Hello"> 
      <TextBlock.Foreground> 
       <SolidColorBrush Color="{TemplateBinding Foreground}"/> 
      </TextBlock.Foreground> 
     </TextBlock> 
    </Border> 
</ControlTemplate> 

注意。 `ActiveColor`を変更し、直接前景ない - ので、それを変更するには、あなたの` TextBlock`が既にActiveColor`プロパティ `にバインドされているの

VisualStateManager.GoToState(annunciator, "Blinking", false); 
+0

ありがとうございます。私は数時間かけて壁に頭を打ちつけ、「束縛を推測する」というゲームをやりました。結局、コードビハインドですべてのことをやったのです。その利点の1つは、すべてのコントロール間でリズムを同期させることができることです。私は戻って、ある時点でVisualStateManagerのアプローチを試してみるかもしれません。もう一度感謝します。 –

関連する問題