2017-08-26 42 views
0

我有一個DataGrid,其中一些列都是這樣XAML設置前景色爲CustomControl當行被選中

<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的前景色。

我該怎麼辦樣式我的自定義控件我的DataGrid強制所有列改變

編輯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

你只需要更新在線(S)顏色(內TextBlock)的每次ForegroundFloatColor變化。困難的方法是在TextBox -properties和inline屬性之間添加綁定。最簡單的方法是要麼添加屬性更改回調依賴屬性或只是通過重寫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) 
      }); 
    } 
} 

同去的FontFamilyFontSize。通過這種方式,只要UpdateTextBlock()使用的任何屬性被更新(無論是通過樣式還是觸發器),控件都會知道它需要更新內部TextBlock中的內聯。

更新8月27日

此外,更新您的Style設置ForegroundFloatColor的制定者,而使用MultiDataTrigger考慮到這兩種行的選中狀態和電網的聚焦狀態。

<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

它的偉大工程,唯一的事情是我必須設置在風格觸發這兩個屬性的前景和FloatColors,用於行甚至和引發LostFocus選擇在數據網格 –

+0

喜娟,如果我明白你的問題吧? - 您不希望Foreground和FloatColor有兩種不同的顏色?然後,您可以簡單地刪除內聯(s)對FloatColor和Foreground的需求。另外,我不相信你需要'MustShowValue()'在lostfocus – Ada

相關問題