2017-08-26 3 views
0

を選択したときに、私はいくつかの列がこのXAML設定フォアグラウンド行が

<DataGridTemplateColumn 
    Width="1.5*" 
    Header="{x:Static lang:Labels.GENERAL_ValorTotal}"> 
    <DataGridTemplateColumn.CellTemplate> 
     <DataTemplate> 
      <sty:DecimalTextBox 
       Text="{Binding Valor,StringFormat=\{0:c3\}}" 
       IsReadOnly="True" 
       Style="{StaticResource DecimalTextBoxGridStyle}"/> 
     </DataTemplate> 
    </DataGridTemplateColumn.CellTemplate> 
</DataGridTemplateColumn> 

enter image description here

ようDataGridTemplateColumnあるデータグリッドを持っている私の問題は、私は、行を選択したときに、私のカスタムコントロールにはないですDataGridTextColumnのように前景色を変更します。

にはどうすれば

編集1つのマイカスタムオブジェクトを変更するには、すべての列を強制的に私のカスタムコントロールや私のデータグリッドのスタイルを行うことができます。

public class DecimalTextBox : TextBox 
{ 

    #region Float Color 
    public static readonly DependencyProperty FloatColorProperty = 
     DependencyProperty.Register("FloatColor", typeof(Color), typeof(DecimalTextBox), new FrameworkPropertyMetadata(Colors.Red)); 
    public Color FloatColor 
    { 
     get { return (Color)GetValue(FloatColorProperty); } 
     set { SetValue(FloatColorProperty, value); } 
    } 
    #endregion 

    #region Show Zero value 
    public bool ShowZeroValue 
    { 
     get { return (bool)GetValue(ShowZeroValueProperty); } 
     set { SetValue(ShowZeroValueProperty, value); } 
    } 
    // Using a DependencyProperty as the backing store for ShowZeroValue. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty ShowZeroValueProperty = 
     DependencyProperty.Register("ShowZeroValue", typeof(bool), typeof(DecimalTextBox), new PropertyMetadata(true)); 
    #endregion 

    protected TextBlock _textBlock; 
    protected FrameworkElement _textBoxView; 

    public DecimalTextBox() 
    { 
     _textBlock = new TextBlock() { Margin = new Thickness(1, 0, 0, 0) }; 
     Loaded += ExTextBox_Loaded; 
    } 

    private void ExTextBox_Loaded(object sender, RoutedEventArgs e) 
    { 
     Loaded -= ExTextBox_Loaded; 

     // hide the original drawing visuals, by setting opacity on their parent 
     var visual = this.GetChildOfType<DrawingVisual>(); 

     if (visual != null) 
     { 
      _textBoxView = (FrameworkElement)visual.Parent; 
      _textBoxView.Opacity = 0; 

      // add textblock to do the text drawing for us 
      var grid = this.GetChildOfType<Grid>(); 
      if (grid.Children.Count >= 2) 
       grid.Children.Insert(1, _textBlock); 
      else 
       grid.Children.Add(_textBlock); 
     } 
    } 

    protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e) 
    { 
     base.OnLostKeyboardFocus(e); 

     _textBoxView.Opacity = 0; 
     _textBlock.Visibility = Visibility.Visible; 
     MustShowValue(); 
    } 

    protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e) 
    { 
     base.OnGotKeyboardFocus(e); 

     _textBoxView.Opacity = 1; 
     _textBlock.Visibility = Visibility.Collapsed; 
    } 

    private bool MustShowValue() 
    { 
     bool show = true; 
     if (!ShowZeroValue && Text == "0") 
     { 
      show = false; 
      _textBlock.Inlines.Clear(); 
      _textBlock.Inlines.Add(new Run 
      { 
       Text = string.Empty, 
       FontFamily = FontFamily, 
       FontSize = FontSize, 
       Foreground = Foreground 
      }); 

      _textBlock.Inlines.Add(new Run 
      { 
       Text = string.Empty, 
       FontFamily = FontFamily, 
       TextDecorations = System.Windows.TextDecorations.Underline, 
       BaselineAlignment = BaselineAlignment.TextTop, 
       FontSize = FontSize * 5/6, 
       Foreground = new SolidColorBrush(FloatColor) 
      }); 
     } 
     return show; 
    } 

    protected override void OnTextChanged(TextChangedEventArgs e) 
    { 
     base.OnTextChanged(e); 

     if (MustShowValue()) 
     { 
      // making sure text on TextBlock is updated as per TextBox 
      var dotPos = Text.IndexOf('.'); 
      var textPart1 = dotPos == -1 ? Text : Text.Substring(0, dotPos + 1); 
      var textPart2 = (dotPos == -1 || dotPos >= (Text.Length - 1)) ? null : Text.Substring(dotPos + 1); 

      _textBlock.Inlines.Clear(); 
      _textBlock.Inlines.Add(new Run 
      { 
       Text = textPart1, 
       FontFamily = FontFamily, 
       FontSize = FontSize, 
       Foreground = Foreground 
      }); 

      if (textPart2 != null) 
       _textBlock.Inlines.Add(new Run 
       { 
        Text = textPart2, 
        FontFamily = FontFamily, 
        TextDecorations = System.Windows.TextDecorations.Underline, 
        BaselineAlignment = BaselineAlignment.TextTop, 
        FontSize = FontSize * 5/6, 
        Foreground = new SolidColorBrush(FloatColor) 
       }); 
     } 
    } 
} 

public static class HelperExtensions 
{ 
    public static T GetChildOfType<T>(this DependencyObject depObj) where T : DependencyObject 
    { 
     if (depObj == null) return null; 

     for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) 
     { 
      var child = VisualTreeHelper.GetChild(depObj, i); 

      var result = (child as T) ?? GetChildOfType<T>(child); 
      if (result != null) return result; 
     } 
     return null; 
    } 
} 


<Style x:Key="DecimalTextBoxGridStyle" TargetType="{x:Type local:DecimalTextBox}"> 
    <Setter Property="TextAlignment" Value="Right"/> 
    <Setter Property="FloatColor" Value="Black"/> 
    <Setter Property="BorderBrush" Value="Transparent"/> 
    <Setter Property="Background" Value="Transparent"/> 
    <Setter Property="ShowZeroValue" Value="False"/> 
    <Style.Triggers> 
     <!--<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}" Value="True"> 
      <Setter Property="Foreground" Value="White"/> 
     </DataTrigger>--> 
    </Style.Triggers> 
</Style> 
+0

「DecimalTextBox」と「DecimalTextBoxGridStyle」のコードを追加できますか? – Fruchtzwerg

+0

@Fruchtzwerg Tksあなたの興味のために。カスタムコードが公開されました。 –

答えて

2

は、あなただけの(内側のTextBlock中)インライン(s)は色ごとにタイムForegroundまたはFloatColor変更を更新する必要があります。難しい方法は、TextBoxのプロパティとインラインプロパティの間にバインディングを追加することです。簡単な方法は、ちょうどOnPropertyChangedをオーバーライドすることにより、プロパティがプロパティを依存関係へのコールバックを変更または追加するか、次のようになります。

例(更新された制御を維持するために OnPropertyChangedを使用して示して)のために

protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) 
{ 
    base.OnPropertyChanged(e); 

    if (e.Property == ForegroundProperty || e.Property == FloatColorProperty) 
     UpdateTextBlock(); //updates the text-block inlines 
} 

protected override void OnTextChanged(TextChangedEventArgs e) 
{ 
    base.OnTextChanged(e); 
    UpdateTextBlock(); // this can be merged to OnPropertyChanged (as text is also dependency property) 
} 

// new extracted method from OnTextChanged 
private void UpdateTextBlock() 
{ 
    if (MustShowValue()) 
    { 
     // making sure text on TextBlock is updated as per TextBox 
     var dotPos = Text.IndexOf('.'); 
     var textPart1 = dotPos == -1 ? Text : Text.Substring(0, dotPos + 1); 
     var textPart2 = (dotPos == -1 || dotPos >= (Text.Length - 1)) ? null : Text.Substring(dotPos + 1); 

     _textBlock.Inlines.Clear(); 
     _textBlock.Inlines.Add(new Run 
     { 
      Text = textPart1, 
      FontFamily = FontFamily, 
      FontSize = FontSize, 
      Foreground = Foreground 
     }); 

     if (textPart2 != null) 
      _textBlock.Inlines.Add(new Run 
      { 
       Text = textPart2, 
       FontFamily = FontFamily, 
       TextDecorations = System.Windows.TextDecorations.Underline, 
       BaselineAlignment = BaselineAlignment.TextTop, 
       FontSize = FontSize * 5/6, 
       Foreground = new SolidColorBrush(FloatColor) 
      }); 
    } 
} 

同じFontFamilyのために行くと、 FontSizeもあります。この方法では、UpdateTextBlock()が使用するプロパティが更新されるたびに、スタイルやトリガを問わず、内部のTextBlockのインラインを更新する必要があることがわかります。

更新また8月27日

、両方の行の選択状態とグリッドの合焦状態を説明するためにMultiDataTriggerを使用している間、セッターでForegroundFloatColorを設定するために、あなたのStyleを更新します。

<Style x:Key="DecimalTextBoxGridStyle" TargetType="{x:Type local:DecimalTextBox}"> 
    <Setter Property="TextAlignment" Value="Right"/> 
    <Setter Property="Foreground" Value="Black"/> 
    <Setter Property="FloatColor" Value="Black"/> 
    <Setter Property="BorderBrush" Value="Transparent"/> 
    <Setter Property="Background" Value="Transparent"/> 
    <Setter Property="ShowZeroValue" Value="False"/> 
    <Style.Triggers> 
     <MultiDataTrigger> 
      <MultiDataTrigger.Conditions> 
       <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridRow}}}" Value="True" /> 
       <Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}, Path=IsKeyboardFocusWithin}" Value="True" /> 
      </MultiDataTrigger.Conditions> 
      <MultiDataTrigger.Setters> 
       <Setter Property="Foreground" Value="White"/> 
       <Setter Property="FloatColor" Value="White"/> 
      </MultiDataTrigger.Setters> 
     </MultiDataTrigger> 
    </Style.Triggers> 
</Style> 
+0

あなたの助けをTks私はそれを見てみるつもりです。 –

+0

それは偉大な、唯​​一のことは、両方のプロパティForeGroundとFloatColorsのためのトリガーを設定する必要がありますRowを選択し、DataGridのLostFocusのために –

+0

こんにちはJuan、私はあなたの質問を正しく理解していますか?フォアグラウンドとフロートカラーの2つの異なる色を必要としませんか?次に、両方のインラインでFloatColorとForegroundの必要性を取り除くだけです。また、私はlostfocusで 'MustShowValue()'が必要であるとは思わない。 – Ada

関連する問題