在 WPF 中,我在画布上创建按钮。像这样。
private void DrawBtnTag( List<ValPosCrt> tagPos)
{
int posNum = tagPos.Count;
StackPanel[] temp = new StackPanel[ posNum ];
Button[] btn = new Button[posNum];
for ( int i = 0 ; i < posNum ; i++ )
{
var btntemp = CheckButton(i);
Canvas.SetLeft( btntemp , tagPos [ i ].X );
Canvas.SetTop( btntemp , tagPos [ i ].Y );
cvsMap.Children.Add( btntemp );
btn [ i ] = btntemp;
}
}
private Button CheckButton( int i ) // done
{
var btn = new Button();
btn.Name = "btn" + i.ToString();
btn.Width = 20;
btn.Height = 20;
btn.VerticalAlignment = VerticalAlignment.Stretch;
btn.HorizontalAlignment = HorizontalAlignment.Stretch;
btn.Click += ClickIdx;
return btn;
}
但是当我运行此代码并扩展应用程序大小时,按钮位置不会更新。
第二张图片是扩展的应用程序大小,我创建的小按钮是行为锚定对象。我想这个按钮跟随背景图像。
Xaml 代码仅此而已
<DockPanel Name="dckPanel" Margin="5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Border CornerRadius="6" BorderThickness="2" BorderBrush="RoyalBlue" DockPanel.Dock="Top" >
<Grid>
<Canvas Name="cvsMap" Grid.Column="0" ClipToBounds="True" Margin="15">
<Canvas.Background>
<ImageBrush x:Name="imgMap" Stretch="Uniform" RenderOptions.BitmapScalingMode="Fant" />
</Canvas.Background>
</Canvas>
</Grid>
</Border>
</DockPanel>
我怎样才能解决这个问题?
** 更新:添加 TestCode ,修复 Xaml 代码。
这是 wpf 项目的测试代码
背后的代码 -
public partial class MainWindow : Window
{ public MainWindow() { InitializeComponent();
List<Point> inputdata = new List<Point>();
inputdata.Add( new Point( 250 , 250 ) );
inputdata.Add( new Point( 250 , 300 ) );
inputdata.Add( new Point( 300 , 250 ) );
inputdata.Add( new Point( 250 , 200 ) );
inputdata.Add( new Point( 200 , 250 ) );
DrawBtnTag( inputdata );
imgMap.ImageSource = createImg();
}
private void DrawBtnTag( List<Point> tagPos ) // done
{
int posNum = tagPos.Count;
StackPanel[] temp = new StackPanel[ posNum ];
Button[] btn = new Button[posNum];
for ( int i = 0 ; i < posNum ; i++ )
{
var btntemp = CheckButton(i);
Canvas.SetLeft( btntemp , tagPos [ i ].X );
Canvas.SetTop( btntemp , tagPos [ i ].Y );
cvsMap.Children.Add( btntemp );
btn [ i ] = btntemp;
}
}
private Button CheckButton( int i ) // done
{
var btn = new Button();
btn.Name = "btn" + i.ToString();
btn.Width = 20;
btn.Height = 20;
btn.VerticalAlignment = VerticalAlignment.Stretch;
btn.HorizontalAlignment = HorizontalAlignment.Stretch;
return btn;
}
public BitmapSource createImg()
{
List<System.Windows.Media.Color> colors = new List<System.Windows.Media.Color>();
colors.Add( System.Windows.Media.Colors.Red );
colors.Add( System.Windows.Media.Colors.Blue );
BitmapPalette palette = new BitmapPalette(colors);
System.Windows.Media.PixelFormat pf =
System.Windows.Media.PixelFormats.Indexed1;
int width = 128;
int height = width;
int stride = width/pf.BitsPerPixel;
byte[] pixels = new byte[height*stride];
for ( int i = 0 ; i < height * stride ; ++i )
{
if ( i < height * stride / 2 )
{
pixels [ i ] = 0x00;
}
else
{
pixels [ i ] = 0xff;
}
}
return BitmapSource.Create(
width,
height,
96,
96,
pf,
palette,
pixels,
stride);
}
}
xaml 代码 - => 与 abaove 的 xaml 代码相同。只需将那个停靠面板放在窗口之后。像这个窗口> .. 这里 ../window>
答案可能有点长,但它应该无需修改即可工作。
基本上:
这是修改后的 XAML 代码:
<Canvas Name="cvsMap" Grid.Column="0" ClipToBounds="True" Margin="15" SizeChanged="cvsMap_SizeChanged">
<Canvas.Background>
<ImageBrush x:Name="imgMap" Stretch="Uniform" RenderOptions.BitmapScalingMode="Fant" />
</Canvas.Background>
</Canvas>
然后是后面的代码(在 createImg 函数之后复制/粘贴):
private void cvsMap_SizeChanged(object sender, SizeChangedEventArgs e)
{
double ratio = imgMap.ImageSource.Width / imgMap.ImageSource.Height;
foreach (Control ctrl in cvsMap.Children)
{
if (ctrl is Button)
{
newBtnPosition((Button)ctrl, ratio, e);
}
}
}
/// <summary>
/// Assign a new position to a ctrl contained into a canvas
/// </summary>
/// <param name="ctrl">control to modify</param>
/// <param name="ratio">ratio of the reference element</param>
/// <param name="e">SizeChanged of the container</param>
private void newBtnPosition(Control ctrl, double ratio, SizeChangedEventArgs e)
{
//Everythong is computed according to the reference element (ImageBrush)
Size oldImgSize, newImgSize;
//Avoid dividing by 0
if (e.PreviousSize.Width * e.PreviousSize.Height * e.NewSize.Width * e.NewSize.Height == 0) { return; }
oldImgSize = RefSize(ratio, e.PreviousSize);
newImgSize = RefSize(ratio, e.NewSize);
Point oldImgPos, newImgPos;
oldImgPos = new Point((e.PreviousSize.Width - oldImgSize.Width) / 2, (e.PreviousSize.Height - oldImgSize.Height) / 2);
newImgPos = new Point((e.NewSize.Width - newImgSize.Width) / 2, (e.NewSize.Height - newImgSize.Height) / 2);
//Retrieve the position of the control according to the ref element
Point ctrlPos = new Point((double)ctrl.GetValue(Canvas.LeftProperty) - oldImgPos.X,
(double)ctrl.GetValue(Canvas.TopProperty) - oldImgPos.Y);
//Compute the new position according to the reference element
ctrlPos.X*=newImgSize.Width / oldImgSize.Width;
ctrlPos.Y *= newImgSize.Height / oldImgSize.Height;
//Assign the new position according to the Canvas
ctrl.SetValue(Canvas.LeftProperty, ctrlPos.X + newImgPos.X);
ctrl.SetValue(Canvas.TopProperty, ctrlPos.Y + newImgPos.Y);
}
/// <summary>
/// Compute a element size, given a aspect ratio, a container size, and a Stretch="Uniform" behavior
/// </summary>
/// <param name="ratio">aspect ratio of the control</param>
/// <param name="containerSize">container size of the control</param>
/// <returns>new size</returns>
private Size RefSize(double ratio, Size containerSize)
{
double cH, cW;
cW = containerSize.Width;
cH = containerSize.Height;
if (cH * cW == 0) { return new Size(0, 0); }
if (cW / cH > ratio)
{
return new Size(cH * ratio, cH);
}
else
{
return new Size(cW, cW/ratio);
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句