背景颜色阻碍WPF UserControl内容 - c#

我有一个UserControl,在XAML中被引用如下:

<local:ColumnGraphRenderCtrl x:Name="graphCtrl" Grid.Column="1" 
    Height="Auto" Width="Auto"/>

所讨论的UserControl具有几种矩形形状,并且显示效果很好。

但是,如果指定Background颜色,则指定的颜色将遮挡矩形,并且仅显示该颜色。例如:

<local:ColumnGraphRenderCtrl x:Name="graphCtrl" Background="Blue" Grid.Column="1" 
    Height="Auto" Width="Auto"/>

(如果我将颜色更改为“透明”,则矩形将变为可见。)

我还尝试对ControlTemplate使用UserControl(作为Style的一部分),但是得到的结果相同(即背景色阻止了UserControl的内容)。

我在MSDN上查找了Control.Background属性,它提供了以下说明:

Background属性仅适用于
控制。控件的默认样式指定其外观
当控件的状态改变时。例如,如果您设置了
Button的Background属性,仅当
没有按下或禁用它。如果要创建一个控件
具有更高级的背景自定义功能,您必须定义
控件的样式。

此属性仅影响控件的模板使用
背景属性作为参数。在其他控件上,此属性
没有影响。

MSDN中的备注的意义是什么?如何在不阻止控件内容的情况下指定背景色?

编辑:如果有区别,将内容控件(矩形)手动添加到代码隐藏中。

UserControl代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;

namespace GraphingWithShapes
{
    public partial class ColumnGraphRenderCtrl: UserControl
    {
        private ObservableCollection<NameValuePair> _dataPoints = null;
        private List<Color> _columnColors = new List<Color>() { Colors.Blue, Colors.Red, Colors.Green };

        public ColumnGraphRenderCtrl()
        {
            InitializeComponent();
        }

        public void SetData(ObservableCollection<NameValuePair> data)
        {
            _dataPoints = data;
            _dataPoints.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_dataPoints_CollectionChanged);
            InvalidateVisual();
        }

        void _dataPoints_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            InvalidateVisual();
        }

        public double GetLargestValue()
        {
            double value = 0;

            foreach (NameValuePair nvp in _dataPoints)
            {
                value = Math.Max(value, nvp.Value);
            }

            return value;
        }

        protected override void OnMouseDoubleClick(MouseButtonEventArgs e)
        {
            base.OnMouseDoubleClick(e);
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            if (_dataPoints != null)
            {
                double spaceToUseY = ActualHeight * 0.8;
                double spaceToUseX = ActualWidth * 0.8;
                double barWidth = spaceToUseX / _dataPoints.Count;
                double largestValue = GetLargestValue();
                double unitHeight = spaceToUseY / largestValue;

                double bottom = ActualHeight * 0.9;
                double left = ActualWidth * 0.1;

                Brush fillBrush;
                Pen outlinePen = new Pen(Brushes.Black, 1);
                int nIndex = 0;
                Rect rect;
                double height;

                foreach (NameValuePair nvp in _dataPoints)
                {
                    fillBrush = new SolidColorBrush(_columnColors[nIndex % _columnColors.Count]);

                    height = (nvp.Value * unitHeight);
                    rect = new Rect(left, bottom - height, barWidth, height);
                    drawingContext.DrawRectangle(fillBrush, outlinePen, rect);

                    left += rect.Width;
                    nIndex++;
                }
            }
        }
    }
}

参考方案

为了编写通过覆盖的OnRender方法进行渲染的自定义控件,您不应从UserControl甚至是Control派生,因为它们是通过ControlTemplate绘制自身的,而Background也会用FrameworkElement笔刷。所有这些操作都在OnRender方法之外完成,因此将其重写而不调用基类的OnRender将无济于事。

相反,从UIElementBackground派生,声明一个属性,并在进行其余渲染之前,用背景填充控制区域:

public class CustomControl : FrameworkElement
{
    public static readonly DependencyProperty BackgroundProperty =
        Control.BackgroundProperty.AddOwner(typeof(CustomControl));

    public Brush Background
    {
        get { return (Brush)GetValue(BackgroundProperty); }
        set { SetValue(BackgroundProperty, value); }
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext); // just good practice
        drawingContext.DrawRectangle(Background, null, new Rect(RenderSize));

        // your rendering code goes here...
    }
}

您可以在MSDN上的Control Authoring Overview文章中找到更多信息。有一节关于从FrameworkElement派生。

当回复有时是一个对象有时是一个数组时,如何在使用改造时解析JSON回复? - java

我正在使用Retrofit来获取JSON答复。这是我实施的一部分-@GET("/api/report/list") Observable<Bills> listBill(@Query("employee_id") String employeeID); 而条例草案类是-public static class…

改造正在返回一个空的响应主体 - java

我正在尝试使用Retrofit和Gson解析一些JSON。但是,我得到的响应机构是空的。当我尝试从对象中打印信息时,出现NullPointerException。我确保URL正确,并且我也确保POJO也正确。我正在使用jsonschema2pojo来帮助创建POJO类。这是我要解析的JSON{ "?xml": { "@versi…

System.out.printf不打印整数参数 - java

我是Java编程的新手,无法从另一个类返回方法。这两个类都可以编译并成功运行。我可以从一个类中调用一个简单的int,但是当我想计算用户输入的两个输入整数时,我只会得到一个空格。这是我的计算课class calculations { public final int AGE = 53; public int numbers(int num1, int num2…

每个文件合并后添加换行 - python

我有很多类似以下内容的JSON文件:例如。1.json{"name": "one", "description": "testDescription...", "comment": ""} test.json{"name"…

Json到php,json_decode返回NULL - php

我正在用PHP进行JSON解析器的一些API,用于存储有关遗产的信息。我在解析时遇到问题,因为它返回的是NULL值而不是数组或对象。简单的JSON代码可以很好地解析,但是可以这样:{"success":true,"totalCount":1,"data":[{"id":99694…