INotifyPropertyChanged 不适用于 Gauge(实时图表)

INotifyPropertyChanged not working on Gauge (Live Charts)

我正在尝试将 Gauge 填充的颜色 属性 绑定到我在后面创建代码的 SolidColorBrush。它适用于进度条但不适用于 Gauge。绑定有效,但它不会像进度条一样自动更新。是否可以在不必重新绘制的情况下更新它?谢谢


XAML:

<Grid Grid.Column="0">
    <lvc:Gauge Grid.Row="2" Grid.Column="0" Margin="5"
               From="0" To="{Binding Path=attaBitrateUP}" Value="{Binding Path=actBitrateUP}" GaugeActiveFill="{Binding Path=up, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
<Grid Grid.Row="2">
   <StackPanel>
     <TextBlock Text="Carrier count:" Height="20" VerticalAlignment="Bottom" Margin="10,0,0,5"/>
          <ProgressBar Height="25" Margin="10,0,10,0" Value="{Binding Path=chartValuesUP}" Maximum="{Binding Path=chartValuesCount}" Foreground="{Binding Path=up}" Background="{Binding Path=down}"/>
   </StackPanel>
</Grid>

隐藏代码:

private SolidColorBrush _up = new SolidColorBrush(Colors.OrangeRed);
public SolidColorBrush up 
{
    get { return _up; }
    set 
    {
         _up = value;
         NotifyPropertyChanged();
     }
}

public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

属性 GaugeActiveFill 没有注册 属性 更改回调。因此,它不会在调用数据绑定时检测到更改。坦率地说,该库实现起来很草率。

但我们可以通过扩展原始 Gauge class 来注册丢失的 属性 更改的处理程序来自己修复它:

FixedGauge.cs

public class FixedGauge : Gauge
{
  static FixedGauge()
  {
    GaugeActiveFillProperty.OverrideMetadata(typeof(FixedGauge), new FrameworkPropertyMetadata(default(Brush), OnGaugeActiveFillChanged));
  }

  private PieSlice PART_Pie { get; set; }

  public FixedGauge()
  {
    this.Loaded += OnLoaded;
  }

  private void OnLoaded(object sender, RoutedEventArgs e)
  {
    if (TryFindVisualChildElementByName(this, null, out PieSlice pie))
    {
      this.PART_Pie = pie;
    }
  }

  private static void OnGaugeActiveFillChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    => (d as FixedGauge).OnGaugeActiveFillChanged(e.OldValue as Brush, e.NewValue as Brush);

  protected virtual void OnGaugeActiveFillChanged(Brush oldBrush, Brush newBrush)
  {
    if (this.PART_Pie == null)
    {
      return;
    }
    this.PART_Pie.Fill = newBrush;
  }

  public static bool TryFindVisualChildElementByName<TChild>(
    DependencyObject parent,
    string childElementName,
    out TChild resultElement) where TChild : FrameworkElement
  {
    resultElement = null;

    if (parent is Popup popup)
    {
      parent = popup.Child;
      if (parent == null)
      {
        return false;
      }
    }

    for (var childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(parent); childIndex++)
    {
      DependencyObject childElement = VisualTreeHelper.GetChild(parent, childIndex);

      if (childElement is TChild frameworkElement)
      {
        if (string.IsNullOrWhiteSpace(childElementName) || frameworkElement.Name.Equals(
          childElementName,
          StringComparison.OrdinalIgnoreCase))
        {
          resultElement = frameworkElement;
          return true;
        }
      }

      if (TryFindVisualChildElementByName(childElement, childElementName, out resultElement))
      {
        return true;
      }
    }

    return false;
  }
}

然后使用这个新控件代替原来的控件:

<local:FixedGauge Grid.Row="2" Grid.Column="0" Margin="5"
                  From="0" To="{Binding Path=attaBitrateUP}" 
                  Value="{Binding Path=actBitrateUP}" 
                  GaugeActiveFill="{Binding Path=up}" />