簡體   English   中英

背景顏色阻礙WPF UserControl內容

[英]Background color obstructs WPF UserControl content

我有一個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屬性僅適用於控件的靜止狀態。 控件的狀態更改時,控件的默認樣式指定其外觀。 例如,如果在“按鈕​​”上設置“背景”屬性,則僅當未按下或禁用按鈕時,該按鈕才具有該值。 如果要創建具有更高級自定義背景的控件,則必須定義控件的樣式。

此屬性僅影響控件的模板使用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畫筆填充了它們的區域。 所有這些操作都是在OnRender方法之外完成的,因此重寫它而不調用基類的OnRender將無濟於事。

取而代之的是,從FrameworkElementUIElement派生,聲明Background屬性,並在進行其余渲染之前,用背景填充控制區域:

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上的“ 控件創作概述”文章中找到更多信息。 有一節關於從FrameworkElement派生。

因此,我的解決方案有效,但您必須擺弄寬度和高度。 在用戶控件中,我添加了一個視圖框和一個統一的網格。

<UserControl x:Class="GraphingWithShapes.ColumnGraphRenderCtrl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Viewbox>
        <UniformGrid x:Name="GraphGrid" />
    </Viewbox>
</UserControl>

然后,根據輸入的數據設置寬度和高度。使列等於數據的數量。 (請注意,我沒有像您一樣輸入更改圖形顏色的邏輯)。 然后,我添加了一個Border(具有邊框和背景),並將其添加到unifrom網格中。 (代碼在這里)

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

        RebuildGraph();
        InvalidateVisual();
    }

    private void RebuildGraph()
    {
        GraphGrid.Children.Clear();
        GraphGrid.Height = GetLargestValue();
        GraphGrid.Width = _dataPoints.Count * 3;
        foreach (var item in _dataPoints)
        {
            AddGraphBar(item.Value);
        }
    }

    private void AddGraphBar(double value)
    {
        Border grid = new Border();
        grid.BorderBrush = Brushes.Black;
        grid.BorderThickness = new Thickness(1);
        grid.Background = Brushes.Green;
        grid.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
        grid.Height = value;
        GraphGrid.Children.Add(grid);
    }

當我在用戶控件上放置背景色后,它現在可以使用了。 我希望這有幫助。

如果使用Visual Studio的模板創建自定義控件,它將創建Generic.xaml文件,該文件為控件提供ControlTemplate。

此模板中的默認設置使它從ControlTemplate復制邊框的背景,這導致背景(在自定義控件的頂部莫名其妙地呈現)背景過度繪制了控件。

<ControlTemplate TargetType="{x:Type local:MyControl}">
    <Border Background="{TemplateBinding Background}">

若要解決此問題,請從ControlTemplate中刪除“ Border Background ”,並渲染背景填充矩形作為您在OnRender中繪制的第一件事:

drawingContext.DrawRectangle(Background, null, new Rect(RenderSize));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM