C# WPF自定义控件/控件模板
我正在使用自定义控件构建一个wpf应用程序,到目前为止一切都正常。C# WPF自定义控件/控件模板,c#,wpf,data-binding,custom-controls,datatemplate,C#,Wpf,Data Binding,Custom Controls,Datatemplate,我正在使用自定义控件构建一个wpf应用程序,到目前为止一切都正常。 但现在我遇到了两个问题: 我想为我的控件指定一个背景色,但它会覆盖网格内的矩形,因此矩形不可见 我试图为ContentControl编写一个模板,但内容没有按预期呈现,这意味着只有显示名称显示在每个进度条的文本中 自定义控件的模板(如果对隐藏的代码感兴趣,我也将添加该模板): ContentControl的模板: <vm:RamViewModel x:Key="RamInformationSource"/> &
但现在我遇到了两个问题:
ContentControl的模板:
<vm:RamViewModel x:Key="RamInformationSource"/>
<Style TargetType="ContentControl" x:Key="MemoryUsageTemplate">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid DataContext="{Binding Source={StaticResource RamInformationSource}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Center" Text="{Binding DisplayName}" VerticalAlignment="Center"
FontSize="15"/>
<ctrl:MetroProgressBar Grid.Column="1" VerticalAlignment="Stretch" Width="55" Orientation="Vertical" HorizontalAlignment="Center"
ExtenedBorderWidth="0.25" BorderBrush="Gray" Text="Available memory" Progress="{Binding AvailableMemory}"
MaxValue="{Binding TotalMemory}"/>
<ctrl:MetroProgressBar Grid.Column="2" VerticalAlignment="Stretch" Width="60" Orientation="Vertical" HorizontalAlignment="Center"
ExtenedBorderWidth="0.2" BorderBrush="Black" Text="Total memory" Progress="100"
MaxValue="{Binding TotalMemory}"/>
<ctrl:MetroProgressBar Grid.Column="3" VerticalAlignment="Stretch" Width="60" Orientation="Vertical" HorizontalAlignment="Center"
ExtenedBorderWidth="0.2" BorderBrush="DodgerBlue" Text="Used memory" Progress="{Binding UsedMemory}"
MaxValue="{Binding TotalMemory}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
显示内容的xaml:
...
<ContentControl Style="{StaticResource MemoryUsageTemplate}"/>
<ctrl:MetroProgressBar Grid.Row="1" BorderBrush="Black" Text="Test" HorizontalAlignment="Left" Background="Aquamarine"
Orientation="Horizontal" BorderThickness="2" Height="50" Width="200" Progress="46"/>
<ctrl:MetroProgressBar Grid.Row="1" BorderBrush="Black" Text="Test" HorizontalAlignment="Right"
Orientation="Horizontal" BorderThickness="2" Height="50" Width="200" Progress="46"/>
...
。。。
...
图像顶部显示应用了模板的内容控件。底部显示了上一个xaml中定义的两个进度条(左带背景,右不带背景)。
这些都是为控件定义的自定义DPs:
/// <summary>
/// Identifies the ExtenedBorderWidth property.
/// </summary>
public static readonly DependencyProperty ExtenedBorderWidthProperty =
DependencyProperty.Register("ExtenedBorderWidth", typeof(double), typeof(MetroProgressBar),
new PropertyMetadata(0.17, ExtendedBorderWidthValueChanged));
/// <summary>
/// Identifies the Text property.
/// </summary>
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(MetroProgressBar), new PropertyMetadata(""));
/// <summary>
/// Identifies the Orientation property.
/// </summary>
public static readonly DependencyProperty OrientationProperty =
DependencyProperty.Register("Orientation", typeof(Orientation), typeof(MetroProgressBar), new PropertyMetadata(Orientation.Horizontal, OrientationValueChanged));
/// <summary>
/// Identifies the IsHorizontal property.
/// </summary>
public static readonly DependencyProperty IsHorizontalProperty =
DependencyProperty.Register("IsHorizontal", typeof(bool), typeof(MetroProgressBar), new PropertyMetadata(true, OrientationChangedByProperty));
/// <summary>
/// Identifies the IsVertical property.
/// </summary>
public static readonly DependencyProperty IsVerticalProperty =
DependencyProperty.Register("IsVertical", typeof(bool), typeof(MetroProgressBar), new PropertyMetadata(false, OrientationChangedByProperty));
/// <summary>
/// Identifies the ProgressBrush property.
/// </summary>
public static readonly DependencyProperty ProgressBrushProperty =
DependencyProperty.Register("ProgressBrush", typeof(Brush), typeof(MetroProgressBar), new PropertyMetadata(new SolidColorBrush(Colors.LightGreen)));
/// <summary>
/// Identifies the LeftBorderTriangle property.
/// </summary>
public static readonly DependencyProperty LeftBorderTriangleProperty =
DependencyProperty.Register("LeftBorderTriangle", typeof(PointCollection), typeof(MetroProgressBar), new PropertyMetadata(new PointCollection()));
/// <summary>
/// Identifies the RightBorderTriangle property.
/// </summary>
public static readonly DependencyProperty RightBorderTriangleProperty =
DependencyProperty.Register("RightBorderTriangle", typeof(PointCollection), typeof(MetroProgressBar), new PropertyMetadata(new PointCollection()));
/// <summary>
/// Identifies the MaxValue property.
/// </summary>
public static readonly DependencyProperty MaxValueProperty =
DependencyProperty.Register("MaxValue", typeof(ulong), typeof(MetroProgressBar), new PropertyMetadata(100UL, MaxValueChanged));
/// <summary>
/// Identifies the Progress property.
/// </summary>
public static readonly DependencyProperty ProgressProperty =
DependencyProperty.Register("Progress", typeof(double), typeof(MetroProgressBar), new PropertyMetadata(0.0d, ProgressValueChanged));
/// <summary>
/// Identifies the ProgressBarWidth property.
/// </summary>
public static readonly DependencyProperty ProgressBarWidthProperty
= DependencyProperty.Register("ProgressBarWidth", typeof(double), typeof(MetroProgressBar), new PropertyMetadata(0.0d));
/// <summary>
/// Identifies the ProgressBarHeight property.
/// </summary>
public static readonly DependencyProperty ProgressBarHeightProperty
= DependencyProperty.Register("ProgressBarHeight", typeof(double), typeof(MetroProgressBar), new PropertyMetadata(0.0d));
//
///标识ExtendedBorderWidth属性。
///
公共静态只读从属属性ExtendedBorderWidthProperty=
DependencyProperty.寄存器(“扩展边界宽度”、typeof(双精度)、typeof(MetroPressBar),
新属性元数据(0.17,ExtendedBorderWidthValueChanged));
///
///标识文本属性。
///
公共静态只读DependencyProperty TextProperty=
DependencyProperty.Register(“文本”、typeof(字符串)、typeof(MetroProPressBar)、new PropertyMetadata(“”);
///
///标识方向属性。
///
公共静态只读DependencyProperty方向属性=
DependencyProperty.Register(“方向”、类型of(方向)、类型of(MetroPressBar)、新属性元数据(方向.水平、方向值更改));
///
///标识IsHorizontal属性。
///
公共静态只读从属属性IsHorizontalProperty=
DependencyProperty.Register(“IsHorizontal”、typeof(bool)、typeof(MetroProgressBar)、新PropertyMetadata(true、OrientationChangedByProperty));
///
///标识IsVertical属性。
///
公共静态只读从属属性IsVerticalProperty=
DependencyProperty.Register(“IsVertical”、typeof(bool)、typeof(MetroProgressBar)、新PropertyMetadata(false、OrientionChangedByProperty));
///
///标识ProgressBrush属性。
///
公共静态只读从属属性ProgressBrushProperty=
DependencyProperty.Register(“ProgressBrush”、typeof(Brush)、typeof(MetroProPressBar)、new PropertyMetadata(new SolidColorBrush(Colors.LightGreen));
///
///标识LeftBorderTriangle属性。
///
公共静态只读从属属性LeftBorderTriangalProperty=
Register(“LeftBorderTriangle”、typeof(PointCollection)、typeof(MetroProgressBar)、newpropertyMetadata(newpointcollection());
///
///标识RightBorderTriangle属性。
///
公共静态只读从属属性RightBorderTriangleProperty=
Register(“RightBorderTriangle”、typeof(PointCollection)、typeof(MetroProPressBar)、new PropertyMetadata(new PointCollection());
///
///标识MaxValue属性。
///
公共静态只读从属属性MaxValueProperty=
DependencyProperty.Register(“MaxValue”、typeof(ulong)、typeof(MetroProgressBar)、新PropertyMetadata(100UL、MaxValueChanged));
///
///标识进度属性。
///
公共静态只读DependencyProperty ProgressProperty=
DependencyProperty.Register(“Progress”、typeof(double)、typeof(MetroPropressBar)、新PropertyMetadata(0.0d,ProgressValueChanged));
///
///标识ProgressBarWidth属性。
///
公共静态只读DependencyProperty ProgressBarWidthProperty
=DependencyProperty.Register(“ProgressBarWidth”、typeof(double)、typeof(MetroProgressBar)、new PropertyMetadata(0.0d));
///
///标识ProgressBarHeight属性。
///
公共静态只读从属属性ProgressBarHeightProperty
=DependencyProperty.Register(“ProgressBarHeight”、typeof(double)、typeof(MetroProgressBar)、new PropertyMetadata(0.0d));
DP值更改了回调和实例方法:
#region Static
/// <summary>
/// Changes the orientation based on the calling property.
/// </summary>
/// <param name="source">The source of the event.</param>
/// <param name="e">Event information.</param>
private static void OrientationChangedByProperty(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
//lock (lockOrientationByProperty)
{
MetroProgressBar pb = source as MetroProgressBar;
if (e.Property == IsVerticalProperty)
{
if ((bool)e.NewValue)
{
pb.IsHorizontal = false;
pb.Orientation = Orientation.Vertical;
}
else
{
pb.IsHorizontal = true;
pb.Orientation = Orientation.Horizontal;
}
}
else
{
// IsVerticalProperty is property that changed
if (!(bool)e.NewValue)
{
pb.IsHorizontal = false;
pb.Orientation = Orientation.Vertical;
}
else
{
pb.IsHorizontal = true;
pb.Orientation = Orientation.Horizontal;
}
}
AdjustVisibleProgressRect(pb);
}
}
/// <summary>
/// Sets the progress value to the new maximum value, if the new max value is less than
/// the current progress value.
/// </summary>
/// <param name="source">The source of the event.</param>
/// <param name="e">Event information.</param>
private static void MaxValueChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
//lock (lockMaxValue)
{
MetroProgressBar pb = source as MetroProgressBar;
ulong val = Convert.ToUInt64(e.NewValue);
if (val < Convert.ToUInt64(pb.Progress))
{
pb.Progress = val;
// Raise finished event
pb.OnFinished(EventArgs.Empty);
}
}
}
/// <summary>
/// Changes the width of the progress indication rectangle of the progress bar.
/// </summary>
/// <param name="source">The source of the event.</param>
/// <param name="e">Event information.</param>
private static void ProgressValueChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
//lock (lockProgress)
{
MetroProgressBar pb = source as MetroProgressBar;
AdjustVisibleProgressRect(pb, (double)e.NewValue);
pb.OnProgressChanged(new ProgressChangedEventArgs((double)e.NewValue));
// If new progress value equals or is greater than max value raise the finished event
if (pb.MaxValue <= Convert.ToUInt64(e.NewValue))
pb.OnFinished(EventArgs.Empty);
}
}
/// <summary>
/// Changes the width of the progress indication rectangle of the progress bar.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">Event information.</param>
private static void OrientationValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
//lock (lockOrientation)
{
MetroProgressBar pb = sender as MetroProgressBar;
pb.AdjustToOrientationChange();
if (pb.Orientation == Orientation.Horizontal)
{
pb.IsVertical = false;
pb.IsHorizontal = true;
}
else
{
pb.IsVertical = true;
pb.IsHorizontal = false;
}
pb.OnOrientationChanged(new OrientationChangedEventArgs((Orientation)e.OldValue, (Orientation)e.NewValue));
}
}
/// <summary>
/// Causes the progress bar to reassign the extended border.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">Event information.</param>
private static void ExtendedBorderWidthValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
//lock (lockExtendedBorder)
{
MetroProgressBar pb = sender as MetroProgressBar;
pb.SetUpBorderParts();
}
}
/// <summary>
/// Adjusts the progress bars visible progress rectangles after progress or visible changes.
/// </summary>
/// <param name="pb">The progress bar that changed.</param>
/// <param name="newValue">The new progress value. Only has to be set if there has been a progress change.</param>
private static void AdjustVisibleProgressRect(MetroProgressBar pb, double newValue = -1)
{
if (pb.Orientation == Orientation.Horizontal)
{
pb.ProgressBarWidth = (newValue == -1 ? pb.Progress : newValue) / pb.MaxValue * pb.Width;
}
else
{
pb.ProgressBarHeight = (newValue == -1 ? pb.Progress : newValue) / pb.MaxValue * pb.Height;
}
}
#endregion
#region Non-Static
/// <summary>
/// Adjusts the border ornaments to the new orientation of the control.
/// </summary>
private void AdjustToOrientationChange()
{
SetUpBorderParts();
}
/// <summary>
/// Sets up the triangles that are placed on the left and right side of the progress bar.
/// </summary>
private void SetUpBorderParts()
{
PointCollection leftBorder = new PointCollection();
PointCollection rightBorder = new PointCollection();
double borderWidth = ExtenedBorderWidth;
if (Orientation == Orientation.Horizontal)
{
// Left triangle
leftBorder.Add(new Point(0, 0));
leftBorder.Add(new Point(0, Height));
leftBorder.Add(new Point(Width * borderWidth, 0));
// Right triangle
rightBorder.Add(new Point(Width, 0));
rightBorder.Add(new Point(Width, Height));
rightBorder.Add(new Point(Width - (Width * borderWidth), Height));
}
else
{
// Top border
leftBorder.Add(new Point(0, 0));
leftBorder.Add(new Point(Width, 0));
leftBorder.Add(new Point(0, Height * borderWidth));
// Bottom border
rightBorder.Add(new Point(0, Height));
rightBorder.Add(new Point(Width, Height));
rightBorder.Add(new Point(Width, Height - (Height * borderWidth)));
}
LeftBorderTriangle = leftBorder;
RightBorderTriangle = rightBorder;
}
/// <summary>
/// Raises the Fnished event.
/// </summary>
/// <param name="e">Information on the event.</param>
protected virtual void OnFinished(EventArgs e)
{
EventHandler handler = finished;
if (handler != null)
{
handler(this, e);
}
}
/// <summary>
/// Raises the ProgressChanged event.
/// </summary>
/// <param name="e">Information on the event.</param>
protected virtual void OnProgressChanged(ProgressChangedEventArgs e)
{
EventHandler<ProgressChangedEventArgs> handler = progressChanged;
if (handler != null)
{
handler(this, e);
}
}
/// <summary>
/// Raises the OrientationChanged event.
/// </summary>
/// <param name="e">Information on the event.</param>
protected virtual void OnOrientationChanged(OrientationChangedEventArgs e)
{
EventHandler<OrientationChangedEventArgs> handler = orientationChanged;
if (handler != null)
{
handler(this, e);
}
}
/// <summary>
/// Raises the RenderSizeChanged event and sets up the border parts.
/// </summary>
/// <param name="sizeInfo">Info on the size change.</param>
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
base.OnRenderSizeChanged(sizeInfo);
SetUpBorderParts();
AdjustVisibleProgressRect(this);
}
#endregion
#区域静态
///
///根据调用属性更改方向。
///
///事件的来源。
///事件信息。
私有静态void方向ChangedByProperty(DependencyObject源、DependencyPropertyChangedEventArgs e)
{
//锁定(lockOrientationByProperty)
{
MetroPressBar pb=源为MetroPressBar;
if(e.Property==IsVerticalProperty)
{
if((bool)e.NewValue)
{
pb.IsHorizontal=假;
pb.方向=方向垂直;
}
其他的
{
pb.IsHorizontal=真;
pb.方向=方向.水平;
}
}
其他的
{
//IsVerticalProperty是已更改的属性
如果(!(bool)e.NewValue)
{
pb.IsHorizontal=假;
pb.方向=方向垂直;
}
其他的
{
pb.IsHorizontal=真;
pb.方向=方向.水平;
}
}
可调整可视进度(pb);
}
}
///
///如果新的最大值为,则将进度值设置为新的最大值
#region Static
/// <summary>
/// Changes the orientation based on the calling property.
/// </summary>
/// <param name="source">The source of the event.</param>
/// <param name="e">Event information.</param>
private static void OrientationChangedByProperty(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
//lock (lockOrientationByProperty)
{
MetroProgressBar pb = source as MetroProgressBar;
if (e.Property == IsVerticalProperty)
{
if ((bool)e.NewValue)
{
pb.IsHorizontal = false;
pb.Orientation = Orientation.Vertical;
}
else
{
pb.IsHorizontal = true;
pb.Orientation = Orientation.Horizontal;
}
}
else
{
// IsVerticalProperty is property that changed
if (!(bool)e.NewValue)
{
pb.IsHorizontal = false;
pb.Orientation = Orientation.Vertical;
}
else
{
pb.IsHorizontal = true;
pb.Orientation = Orientation.Horizontal;
}
}
AdjustVisibleProgressRect(pb);
}
}
/// <summary>
/// Sets the progress value to the new maximum value, if the new max value is less than
/// the current progress value.
/// </summary>
/// <param name="source">The source of the event.</param>
/// <param name="e">Event information.</param>
private static void MaxValueChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
//lock (lockMaxValue)
{
MetroProgressBar pb = source as MetroProgressBar;
ulong val = Convert.ToUInt64(e.NewValue);
if (val < Convert.ToUInt64(pb.Progress))
{
pb.Progress = val;
// Raise finished event
pb.OnFinished(EventArgs.Empty);
}
}
}
/// <summary>
/// Changes the width of the progress indication rectangle of the progress bar.
/// </summary>
/// <param name="source">The source of the event.</param>
/// <param name="e">Event information.</param>
private static void ProgressValueChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
//lock (lockProgress)
{
MetroProgressBar pb = source as MetroProgressBar;
AdjustVisibleProgressRect(pb, (double)e.NewValue);
pb.OnProgressChanged(new ProgressChangedEventArgs((double)e.NewValue));
// If new progress value equals or is greater than max value raise the finished event
if (pb.MaxValue <= Convert.ToUInt64(e.NewValue))
pb.OnFinished(EventArgs.Empty);
}
}
/// <summary>
/// Changes the width of the progress indication rectangle of the progress bar.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">Event information.</param>
private static void OrientationValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
//lock (lockOrientation)
{
MetroProgressBar pb = sender as MetroProgressBar;
pb.AdjustToOrientationChange();
if (pb.Orientation == Orientation.Horizontal)
{
pb.IsVertical = false;
pb.IsHorizontal = true;
}
else
{
pb.IsVertical = true;
pb.IsHorizontal = false;
}
pb.OnOrientationChanged(new OrientationChangedEventArgs((Orientation)e.OldValue, (Orientation)e.NewValue));
}
}
/// <summary>
/// Causes the progress bar to reassign the extended border.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">Event information.</param>
private static void ExtendedBorderWidthValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
//lock (lockExtendedBorder)
{
MetroProgressBar pb = sender as MetroProgressBar;
pb.SetUpBorderParts();
}
}
/// <summary>
/// Adjusts the progress bars visible progress rectangles after progress or visible changes.
/// </summary>
/// <param name="pb">The progress bar that changed.</param>
/// <param name="newValue">The new progress value. Only has to be set if there has been a progress change.</param>
private static void AdjustVisibleProgressRect(MetroProgressBar pb, double newValue = -1)
{
if (pb.Orientation == Orientation.Horizontal)
{
pb.ProgressBarWidth = (newValue == -1 ? pb.Progress : newValue) / pb.MaxValue * pb.Width;
}
else
{
pb.ProgressBarHeight = (newValue == -1 ? pb.Progress : newValue) / pb.MaxValue * pb.Height;
}
}
#endregion
#region Non-Static
/// <summary>
/// Adjusts the border ornaments to the new orientation of the control.
/// </summary>
private void AdjustToOrientationChange()
{
SetUpBorderParts();
}
/// <summary>
/// Sets up the triangles that are placed on the left and right side of the progress bar.
/// </summary>
private void SetUpBorderParts()
{
PointCollection leftBorder = new PointCollection();
PointCollection rightBorder = new PointCollection();
double borderWidth = ExtenedBorderWidth;
if (Orientation == Orientation.Horizontal)
{
// Left triangle
leftBorder.Add(new Point(0, 0));
leftBorder.Add(new Point(0, Height));
leftBorder.Add(new Point(Width * borderWidth, 0));
// Right triangle
rightBorder.Add(new Point(Width, 0));
rightBorder.Add(new Point(Width, Height));
rightBorder.Add(new Point(Width - (Width * borderWidth), Height));
}
else
{
// Top border
leftBorder.Add(new Point(0, 0));
leftBorder.Add(new Point(Width, 0));
leftBorder.Add(new Point(0, Height * borderWidth));
// Bottom border
rightBorder.Add(new Point(0, Height));
rightBorder.Add(new Point(Width, Height));
rightBorder.Add(new Point(Width, Height - (Height * borderWidth)));
}
LeftBorderTriangle = leftBorder;
RightBorderTriangle = rightBorder;
}
/// <summary>
/// Raises the Fnished event.
/// </summary>
/// <param name="e">Information on the event.</param>
protected virtual void OnFinished(EventArgs e)
{
EventHandler handler = finished;
if (handler != null)
{
handler(this, e);
}
}
/// <summary>
/// Raises the ProgressChanged event.
/// </summary>
/// <param name="e">Information on the event.</param>
protected virtual void OnProgressChanged(ProgressChangedEventArgs e)
{
EventHandler<ProgressChangedEventArgs> handler = progressChanged;
if (handler != null)
{
handler(this, e);
}
}
/// <summary>
/// Raises the OrientationChanged event.
/// </summary>
/// <param name="e">Information on the event.</param>
protected virtual void OnOrientationChanged(OrientationChangedEventArgs e)
{
EventHandler<OrientationChangedEventArgs> handler = orientationChanged;
if (handler != null)
{
handler(this, e);
}
}
/// <summary>
/// Raises the RenderSizeChanged event and sets up the border parts.
/// </summary>
/// <param name="sizeInfo">Info on the size change.</param>
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
base.OnRenderSizeChanged(sizeInfo);
SetUpBorderParts();
AdjustVisibleProgressRect(this);
}
#endregion