- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我们开发了一个简单的 WPF UserControl,它是一个 ChartLine,通常应该显示 512 个值,范围在 -100 到 100 之间。该图表有效,但是,图表需要每 1 秒清除和更新一次其值,并且它需要一秒钟(1.4~~秒)来简单地呈现其所有值。在这次失败的尝试之后,我尝试使用 Microsoft 的旧 DynamicDataDisplay (D3),它应该更快,但对性能的影响是完全相同的,更新屏幕上的 512 值也需要一秒多的时间。
下面是我的代码,我相信可能有一些缓存技术、较低的位图分辨率或其他有助于实现我的目标的东西。
XAML:
<UserControl x:Class="IHM.OsciloscopeGraphic"
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"
xmlns:local="clr-namespace:IHM"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="740" Loaded="UserControl_Loaded">
<Grid x:Name="gdMain">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:OsciloscopeGraphic}}, Path=TitleGreen}" HorizontalAlignment="Right" HorizontalContentAlignment="Center" Margin="10, 0" FontSize="18" Width="115" Background="Green"/>
<Label Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:OsciloscopeGraphic}}, Path=TitleLightBlue}" FontSize="18" Margin="10, 0" HorizontalAlignment="Left" HorizontalContentAlignment="Center" Background="LightBlue" Grid.Column="1" Width="115"/>
<Grid Name="gdChartArea" Grid.Row="1" Grid.ColumnSpan="2" >
<Border BorderBrush="Black" BorderThickness="1" Margin="30, 10, 10, 30"/>
<Canvas x:Name="cnvChart" Margin="30, 10, 10, 30">
<Canvas.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#4C000080" Offset="1"/>
<GradientStop Color="#4C7F7FFF"/>
</LinearGradientBrush>
</Canvas.Background>
</Canvas>
</Grid>
</Grid>
C#代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Shapes;
namespace IHM
{
public partial class OsciloscopeGraphic : UserControl
{
#region Properties
/// <summary>
/// If steps Lines are 0, will divide the grid equally by the number in lines grid
/// </summary>
public int LinesGrid { get; set; }
/// <summary>
/// If steps Columns are 0, will divide the grid equally by the number in lines grid
/// </summary>
public int ColumnsGrid { get; set; }
public int StepsLines { get; set; }
public int StepsColumns { get; set; }
public int MaxHorizontal { get; set; }
public int MaxVertical { get; set; }
public int MinHorizontal { get; set; }
public int MinVertical { get; set; }
public static readonly DependencyProperty TitleGreenProperty =
DependencyProperty.Register("TitleGreen", typeof(string), typeof(BarGraphicSplitted), new UIPropertyMetadata("TRS"));
[Bindable(true)]
public string TitleGreen
{
get { return (string)GetValue(TitleGreenProperty); }
set { SetValue(TitleGreenProperty, value); }
}
public static readonly DependencyProperty TitleLightBlueProperty =
DependencyProperty.Register("TitleLightBlue", typeof(string), typeof(BarGraphicSplitted), new UIPropertyMetadata("FRT"));
[Bindable(true)]
public string TitleLightBlue
{
get { return (string)GetValue(TitleLightBlueProperty); }
set { SetValue(TitleLightBlueProperty, value); }
}
#endregion Properties
#region Local Fields/Variables
private bool initialized = false;
private int Quantidade
{
get { return (Math.Abs(this.MaxHorizontal - this.MinHorizontal) + 1); }
}
#endregion Local Fields/Variables
public OsciloscopeGraphic()
{
InitializeComponent();
this.MaxHorizontal = 255;
this.MinHorizontal = 0;
this.MaxVertical = 100;
this.MinVertical = -100;
this.LinesGrid = 0;
this.ColumnsGrid = 0;
this.StepsColumns = 10;
this.StepsLines = 10;
}
#region Private Local/Methods
private Line CreateGridLine()
{
Line lm = new Line();
lm.Stroke = Brushes.Black;
lm.StrokeThickness = 1;
lm.StrokeDashArray = new DoubleCollection() { 1, 4 };
lm.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
return lm;
}
private Line CreateHorizontalGridLine(Point start, double length)
{
Line ln = CreateGridLine();
//It has the same value because the line will be a vertical line
ln.X1 = start.X;
ln.X2 = start.X + length;
ln.Y1 = start.Y;
ln.Y2 = start.Y;
return ln;
}
private Line CreateHorizontalScaleLine(Point start)
{
Line l = CreateScaleLine();
l.X1 = start.X;
l.X2 = start.X - 5;
l.Y1 = start.Y;
l.Y2 = start.Y;
return l;
}
private Line CreateScaleLine()
{
Line l = new Line();
l.Stroke = Brushes.Black;
l.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
return l;
}
private Line CreateVerticalGridLine(Point start, double length)
{
Line ln = CreateGridLine();
//It has the same value because the line will be a vertical line
ln.X1 = start.X;
ln.X2 = start.X;
ln.Y1 = start.Y;
ln.Y2 = start.Y + length;
return ln;
}
private Line CreateVerticalScaleLine(Point start)
{
Line l = CreateScaleLine();
l.X1 = start.X;
l.X2 = start.X;
l.Y1 = start.Y;
l.Y2 = start.Y + 5;
return l;
}
private void DrawGrid(Grid grid, Canvas chart)
{
bool makeBySteps = true;
if ((this.StepsColumns == 0) || (this.StepsLines == 0))
{
makeBySteps = false;
if ((this.LinesGrid == 0) || (this.ColumnsGrid == 0))
throw new DivideByZeroException();
}
//get canvas absolute position
var getPos = chart.TransformToVisual(grid);
Point XYpos = getPos.Transform(new Point(0, 0));
//draw the lines
double actualWidth = (chart.ActualWidth);
double initialPosition = (XYpos.X + 1);
double length = this.MaxHorizontal - this.MinHorizontal + 1;
double stepLegend = (makeBySteps) ? this.StepsColumns : length / Convert.ToDouble(this.ColumnsGrid);
int counter = (makeBySteps) ? ((int)length) / this.StepsColumns : this.ColumnsGrid;
double step = (makeBySteps) ? (actualWidth / length) * this.StepsColumns : (actualWidth / this.ColumnsGrid);
length = Math.Abs(length);
double remainder = 0d;
for (int i = 0; i <= counter; i++)
{
//vertical gridlines
double steps = i * step;
Point start = new Point(initialPosition + steps, XYpos.Y);
Line Lm = CreateVerticalGridLine(start, chart.ActualHeight);
grid.Children.Add(Lm);
//vertical scale lines
Point startScale = new Point(initialPosition + steps, XYpos.Y + chart.ActualHeight);
Line LineScale = CreateVerticalScaleLine(startScale);
grid.Children.Add(LineScale);
//bottom labels
Label lb = new Label();
lb.Width = 20;
lb.Height = 20;
lb.Padding = new Thickness(0);
lb.HorizontalContentAlignment = HorizontalAlignment.Center;
lb.ClipToBounds = false;
//this garantes that it will consider the reminder of divisions
double numero = this.MinHorizontal + (i * stepLegend);
remainder += numero - Math.Round(numero);
numero = Math.Round(numero);
if (remainder > 1)
{
remainder -= 1;
numero += 1;
}
else if (remainder < -1)
{
remainder += 1;
numero -= 1;
}
lb.Content = numero;
grid.Children.Add(lb);
lb.HorizontalAlignment = HorizontalAlignment.Left;
lb.VerticalAlignment = VerticalAlignment.Top;
//TODO: big coment explaining in details the line bellow
lb.Margin = new Thickness((XYpos.X - 10) + steps, XYpos.Y + chart.ActualHeight + 5, 0, 0);
}
initialPosition = XYpos.Y;
double actualHeight = (chart.ActualHeight);
length = this.MaxVertical - this.MinVertical + 1;
stepLegend = (makeBySteps) ? this.StepsLines : length / Convert.ToDouble(this.LinesGrid);
counter = (makeBySteps) ? ((int)length) / this.StepsLines : this.LinesGrid;
step = (makeBySteps) ? (actualHeight / length) * this.StepsLines : (actualHeight / this.LinesGrid);
//initialPosition = (makeBySteps) ? initialPosition + ((actualHeight / length) * (length % this.StepsLines)) : initialPosition;
length = Math.Abs(length);
remainder = 0d;
for (int i = 0; i <= counter; i++)
{
double steps = i * step;
Point start = new Point(XYpos.X, actualHeight + initialPosition - steps);
//horizontal gridlines
Line lm = CreateHorizontalGridLine(start, actualWidth);
grid.Children.Add(lm);
//horizontal scale lines
Line l = CreateHorizontalScaleLine(start);
grid.Children.Add(l);
//side labels
Label lb = new Label();
lb.Width = 30;
lb.Height = 20;
lb.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Right;
lb.Padding = new Thickness(0);
lb.VerticalContentAlignment = VerticalAlignment.Center;
lb.ClipToBounds = false;
//this garantes that it will consider the reminder of divisions
double numero = this.MinVertical + (i * stepLegend);
remainder += numero - Math.Round(numero);
numero = Math.Round(numero);
if (remainder > 1)
{
remainder -= 1;
numero += 1;
}
else if (remainder < -1)
{
remainder += 1;
numero -= 1;
}
lb.Content = numero;
grid.Children.Add(lb);
lb.HorizontalAlignment = HorizontalAlignment.Left;
lb.VerticalAlignment = VerticalAlignment.Top;
//TODO: big coment explaining in details the line bellow
lb.Margin = new Thickness(XYpos.X - 37, start.Y - 10, 0, 0);
}
}
private void DrawGrid()
{
this.DrawGrid(gdChartArea, cnvChart);
}
private void DrawLine(List<int> p_values, SolidColorBrush cor)
{
Polyline cl = new Polyline();
cl.Stroke = cor;
cl.StrokeThickness = 2;
cl.StrokeLineJoin = PenLineJoin.Round;
//cl.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
double stepHorizontal = cnvChart.ActualWidth / ((this.MaxHorizontal - this.MinHorizontal) + 1);
double stepVertical = cnvChart.ActualHeight / ((this.MaxVertical - this.MinVertical) + 1);
for (int i = 0; i < p_values.Count; i++)
{
int val = p_values[i];
double x = (stepHorizontal * i);
double y = cnvChart.ActualHeight - ((val - this.MinVertical) * stepVertical);
cl.Points.Add(new Point(x, y));
}
cnvChart.Children.Add(cl);
}
private void DrawLineGreen(List<int> p_values)
{
DrawLine(p_values, Brushes.Green);
}
private void DrawLineLightBlue(List<int> p_values)
{
DrawLine(p_values, Brushes.LightBlue);
}
private List<int> GetRandomValues()
{
int quantidade = this.Quantidade;
List<int> lsValues = new List<int>(quantidade);
int seed = 0;
long ticks = DateTime.Now.Ticks;
while (ticks > int.MaxValue)
{
ticks -= int.MaxValue;
}
seed = Convert.ToInt32(ticks);
Random ran = new Random(seed);
for (int i = 0; i < quantidade; i++)
{
int randomValue = ran.Next(this.MinVertical, this.MaxVertical);
lsValues.Add(randomValue);
}
return lsValues;
}
#endregion Private Local/Methods
#region Public Methods
public void Clear()
{
this.cnvChart.Children.Clear();
}
public void UpdateGraphValues()
{
UpdateGraphValues(GetRandomValues(), GetRandomValues());
}
public void UpdateGraphValues(List<int> p_frontValues, List<int> p_backValues)
{
//Clear current graphic values.
Clear();
DrawLineGreen(p_frontValues);
DrawLineLightBlue(p_backValues);
}
#endregion Public Methods
#region Window Events
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
if (!initialized)
{
DrawGrid();
UpdateGraphValues();
initialized = true;
}
}
#endregion Window Events
}
}
要在我希望的条件下测试图形,您可以简单地实例化`
private OsciloscopeGraphic graphicOscNormal = new OsciloscopeGraphic()
{
MinHorizontal = 0,
MaxHorizontal = 255,
MinVertical = -100,
MaxVertical = 100
};
在计时器内,您可以调用 `graphicOscNormal.UpdateGraphValues()
` 这将使用随机值填充图形以用于测试目的。稍后这些值将来自已经实现的串口。
注意:我也尝试用 DrawingVisual 和 DrawingContext.DrawLine 替换高级折线,但性能没有改变!
注意 2:我使用的是 C#/WPF 和 .NET 4.0 (VS 2010)。
提前致谢,Luís。
最佳答案
(最大的)问题是您的随机数生成器 - 它效率极低。尝试:
private Random ran = new Random(0);
private List<int> GetRandomValues()
{
int quantidade = this.Quantidade;
List<int> lsValues = new List<int>(quantidade);
for (int i = 0; i < quantidade; i++)
{
int randomValue = ran.Next(this.MinVertical, this.MaxVertical);
lsValues.Add(randomValue);
}
return lsValues;
}
在优化时,对配置文件有好处。
如果您真的想要真的快速渲染,那么您几乎必须回到 GDI。例如 - 更新您的 Canvas
(cnvChart) 以使用此 FastCanvas
:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows;
using System.Windows.Interop;
using System.Runtime.InteropServices;
using System.Drawing.Drawing2D;
namespace WpfApplication1
{
class FastCanvas : Canvas
{
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateFileMapping(IntPtr hFile,
IntPtr lpFileMappingAttributes,
uint flProtect,
uint dwMaximumSizeHigh,
uint dwMaximumSizeLow,
string lpName);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject,
uint dwDesiredAccess,
uint dwFileOffsetHigh,
uint dwFileOffsetLow,
uint dwNumberOfBytesToMap);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool UnmapViewOfFile(IntPtr lbBaseAddress);
protected System.Drawing.Graphics GDIGraphics;
protected InteropBitmap interopBitmap = null;
protected InteropBitmap buffBitmap = null;
private const uint FILE_MAP_ALL_ACCESS = 0xF001F;
private const uint PAGE_READWRITE = 0x04;
private int bpp = PixelFormats.Bgra32.BitsPerPixel / 8;
protected IntPtr MapViewPointer;
public struct ScopeLine
{
public SolidColorBrush lineBrush;
public List<Point> linePoints;
}
public List<ScopeLine> Lines = new List<ScopeLine>();
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
if (Lines.Count() > 0)
{
ImageSource drIs = null;
if (interopBitmap == null)
{
uint byteCount = (uint)((int)this.ActualWidth * (int)this.ActualHeight * bpp);
var fileMappingPointer = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, PAGE_READWRITE, 0, byteCount, null);
this.MapViewPointer = MapViewOfFile(fileMappingPointer, FILE_MAP_ALL_ACCESS, 0, 0, byteCount);
PixelFormat format = PixelFormats.Bgra32;
var stride = (int)((int)this.ActualWidth * format.BitsPerPixel / 8);
this.interopBitmap = Imaging.CreateBitmapSourceFromMemorySection(fileMappingPointer,
(int)this.ActualWidth,
(int)this.ActualHeight,
format,
stride,
0) as InteropBitmap;
this.GDIGraphics = GetGdiGraphics(MapViewPointer);
}
GDIGraphics.FillRectangle(System.Drawing.Brushes.Transparent,
new System.Drawing.Rectangle(0, 0,
(int)this.ActualWidth,
(int)this.ActualHeight));
foreach (ScopeLine dLine in Lines)
{
var pointCount = dLine.linePoints.Count();
Color lpColour;
lpColour = dLine.lineBrush.Color;
System.Drawing.Color lp2Colour;
lp2Colour = System.Drawing.Color.FromArgb(lpColour.A,
lpColour.R,
lpColour.G,
lpColour.B);
System.Drawing.Pen lpPen = new System.Drawing.Pen(lp2Colour, 1.5f);
System.Drawing.PointF newPoint = new System.Drawing.PointF((float)dLine.linePoints[0].X,
(float)dLine.linePoints[0].Y);
for (int i = 0; i < pointCount - 1; i++)
{
System.Drawing.PointF newPoint1 = new System.Drawing.PointF((float)dLine.linePoints[i + 1].X,
(float)dLine.linePoints[i + 1].Y);
GDIGraphics.DrawLine(lpPen, newPoint, newPoint1);
newPoint = newPoint1;
}
}
var bmpsrc = interopBitmap.GetAsFrozen();
if (bmpsrc == null || bmpsrc.CheckAccess())
{
drIs = (System.Windows.Media.Imaging.BitmapSource)bmpsrc;
}
else
{
//Debug.WriteLine("No access to TheImage");
}
dc.DrawImage(drIs, new Rect(this.RenderSize));
}
}
private System.Drawing.Graphics GetGdiGraphics(IntPtr mapViewPointer)
{
System.Drawing.Graphics gdiGraphics;
System.Drawing.Bitmap gdiBitmap;
gdiBitmap = new System.Drawing.Bitmap((int)this.ActualWidth,
(int)this.ActualHeight,
(int)this.ActualWidth * bpp,
System.Drawing.Imaging.PixelFormat.Format32bppArgb,
mapViewPointer);
gdiGraphics = System.Drawing.Graphics.FromImage(gdiBitmap);
gdiGraphics.CompositingMode = CompositingMode.SourceCopy;
gdiGraphics.CompositingQuality = CompositingQuality.HighSpeed;
gdiGraphics.SmoothingMode = SmoothingMode.HighSpeed;
return gdiGraphics;
}
}
}
并将您的 DrawLine
更改为:
private void DrawLine(List<int> p_values, SolidColorBrush cor)
{
double stepHorizontal = cnvChart.ActualWidth / ((this.MaxHorizontal - this.MinHorizontal) + 1);
double stepVertical = cnvChart.ActualHeight / ((this.MaxVertical - this.MinVertical) + 1);
List<Point> pts = new List<Point>();
for (int i = 0; i < p_values.Count; i++)
{
int val = p_values[i];
double x = (stepHorizontal * i);
double y = cnvChart.ActualHeight - ((val - this.MinVertical) * stepVertical);
pts.Add(new Point(x,y));
}
FastCanvas.ScopeLine newLine;
newLine.lineBrush = cor;
newLine.linePoints = pts;
cnvChart.Lines.Add(newLine);
}
和 UpdateValues
到:
public void UpdateGraphValues(List<int> p_frontValues, List<int> p_backValues)
{
cnvChart.Lines.Clear();
DrawLineGreen(p_frontValues);
DrawLineLightBlue(p_backValues);
cnvChart.InvalidateVisual();
}
与使用 WPF 渲染时大约 5-7fps 相比,像这样使用 GDI 相同的图形可以实时更新(对于 512 个点轻松 > 30fps)。
关于c# - WPF 自定义 ChartLine 性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17969146/
有没有办法在另一个 WPF 窗口内托管 WPF 窗口。我有几个有点复杂的表格。但现在为了简化事情,我试图将其中一些合并为一个“仪表板”表单中的标签页。 请注意,我不是要托管 Windows 窗体,而是
WPF 特有的哪些方面和实践在非 WPF GUI 编程中最有用(并且并非难以实现)? 最佳答案 通过学习 WPF 命令,我了解了命令模式。它构成了 UI - 代码分离的基础,我认为应该在其他应用程序中
WinRT/Metro 正在获得一个新的 SemanticZoom控制,但我很难为 WPF 找到任何东西。 我不想为我的特定项目切换到 Metro,因为它不允许我制作窗口应用程序或跨多个显示器的多个实
我很难解决我的问题,我快要疯了。 想法是这样的:我有两个 ListView 元素,当一个元素从第一个列表掉落到第二个列表时,我需要打开一个对话,但我需要被掉落的元素的信息以及被添加以填充对话的元素。
如果我遵循TabControl,并且一切正常,当我切换到第二个Tabitem时,它显示就没有问题。 //datagrid //datagrid2 但是如果我有这个xaml,当我
在 Windows 窗体应用程序中,我们的数据 GridView 有很多事件,如行鼠标双击或行单击以及额外的...... 但是在 WPF 中我找不到这些事件。我如何将行鼠标双击添加到其中包含数据网格的
在这个项目中,代码 正确编译和执行 ;但是,我需要帮助解决两个问题: VS2012 WPF 设计器不适用于此 XAML 文件。它显示消息设计 View 对于 x64 和 ARM 目标平台不可用。 我收
目前我正在设计 WPF ScrollViewer,我发现了这个 Content="M 0 0 L 4 4 L 0 8 Z" 阅读 MSDN examples .现在我真的很想知道这意味着什么,但我无法
在 WPF 中,元素的可见性可以为“可见”,但实际上在屏幕上不可见,因为它的父元素(或父元素的父元素)具有折叠的可见性。 我希望能够知道一个元素是否实际呈现在屏幕上,而不必遍历可视化树检查父元素。 有
我应该使用 ApplicationCommands.Close用于关闭模式对话框还是该命令被认为是为关闭应用程序保留的?如果是后者,请大家创建Close每个命令 Dialog盒子或只是一个 Close
WPF 是否有任何可用的 piemenu 控件? 最佳答案 我在我的最爱中找到了这个,你可以看看: This 祝你今天过得愉快。 关于wpf - WPF 的菜单,我们在Stack Overflow上找
我正在尝试使用 WrapPanel 和两个 TextBlock 将星号 (*) 附加到某些文本的左侧,允许文本换行,并强制文本右对齐。通过创建一个 FlowDirection 设置为 RightToL
这里是场景(简化):我在Window上有一个控件(比如说一个Rectangle)。我迷上了MouseMove事件,以使其启动拖放操作。然后在MouseDown事件中进行动画处理,向右移动50个像素。但
我有一个 ListView ,它的项目来源是一个列表。我希望用户只选择一项。当我将 listview 的 SelectionMode 设置为 single 时,用户仍然可以选择多个项目,并且似乎 li
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
INotifyPropertyChanged 的目的是什么。我知道每当更改属性时都会触发此事件,但是 View /用户界面如何知道触发了此事件: 这是实现 INotifyPropertyChang
我正在查看工具箱中的 WPF 组件,但找不到 2005/2008 中存在的错误提供程序。 被移除了吗? 最佳答案 ErrorProvider是一个 Winforms 控件。 WPF 中没有等效项。但是
我试图在单击和双击 wpf Image 控件时有不同的行为。不幸的是,单击首先被触发,因此双击被忽略。 最佳答案 如果您改用 MouseDown 事件,则它在 EventArgs 中为 ClickCo
这可能吗? 我使用了一个框架控件并且:显示(例如:showwindow.xaml) 但是我得到这个错误: root element is not valid for navigation 最佳答案 确
我在蓝色背景的窗口上放置了一个扩展器,我想让扩展器的按钮与默认颜色不同(蓝色,它是从窗口接收的)。当我修改扩展器的背景属性时,它会将整个扩展器、标题和全部更改为新颜色。但是,我只想更改按钮本身。谁能指
我是一名优秀的程序员,十分优秀!