有一个代码来显示一个圆(使用宽度和高度相等的ellipse
,并且还使用reactive ui
进行通知)我想在画布中间绘制一个圆,但是管理调整大小的更新。
当前代码设置了Canvas Left
和Canvas Top
,但是我不确定如何在中间设置圆圈并填充几乎所有画布。
public class MyViewModel : ReactiveObject
{
public ObservableCollection<IShape> Shapes
{
get => _shapes;
set => this.RaiseAndSetIfChanged(ref _shapes, value);
}
private ObservableCollection<IShape> _shapes;
public MainViewModel()
{
//here the location is set, but how to adjust it to the center of canvas?
Shapes = new ObservableCollection<IShape>
{
new Circle {
Top = 100,
Left = 100,
Radius = 50,
Color = Color.FromArgb(255, 233,222, 0)
}
};
}
}
public interface IShape
{
int Top { get; set; }
int Left { get; set; }
}
public abstract class Shape : ReactiveObject, IShape
{
private int _top;
private int _left;
public int Top
{
get { return _top; }
set { this.RaiseAndSetIfChanged(ref _top, value); }
}
public int Left
{
get { return _left; }
set { this.RaiseAndSetIfChanged(ref _left, value); }
}
}
public class Circle : Shape
{
private int _radius;
private Color _color;
public int Radius
{
get => _radius;
set => this.RaiseAndSetIfChanged(ref _radius, value);
}
public System.Windows.Media.Color Color
{
get => _color;
set => this.RaiseAndSetIfChanged(ref _color, value);
}
}
<ItemsControl ItemsSource="{Binding Path=Shapes}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type entities:Circle}">
<Ellipse Width="{Binding Radius}"
Height="{Binding Radius}"
Canvas.Top="{Binding Top, Mode=TwoWay}"
Canvas.Left="{Binding Left, Mode=TwoWay}"
>
<Ellipse.Stroke>
<SolidColorBrush Color="{Binding Color}" />
</Ellipse.Stroke>
</Ellipse>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Top" Value="{Binding Path=Top, Mode=TwoWay}" />
<Setter Property="Canvas.Left" Value="{Binding Path=Left, Mode=TwoWay}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
这将产生:
如何更改 xaml 或后面的代码以居中并将圆几乎设置为画布大小?
答案 0 :(得分:1)
通过将椭圆大小绑定到画布大小并使用将输入值转换为(例如)画布大小的0.9倍的转换器,使椭圆几乎与画布一样大,如下所示:< / p>
XAML
<Canvas Name="MyCanvas">
<Ellipse Height="{Binding ElementName=MyCanvas, Path=ActualHeight, Converter={StaticResource MyScaleConverter}}" Width="{Binding ElementName=MyCanvas, Path=ActualWidth, Converter={StaticResource MyScaleConverter}}"></Ellipse>
</Canvas>
C#
public class ScaleZeroNine : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return System.Convert.ToDouble(value) * 0.9;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
关于中心问题: 为什么还要用画布?是否有特定原因? Canvas使得使用WPF的全部功能变得困难,因为其布局更像winForms。例如,当使用网格时,它将自动居中,也可以定义为居中
答案 1 :(得分:0)
给椭圆一个渲染变换:
<Ellipse Width="50" Height="50" Fill="Yellow" Stroke="CornflowerBlue" StrokeThickness="
<Ellipse.RenderTransform>
<TranslateTransform X="-25" Y="-25" /> <!-- center the ellipse -->
</Ellipse.RenderTransform>
</Ellipse>
答案 2 :(得分:0)
为补充答案,我在自定义值转换器中使用了多重绑定。
public class HalfValueConverter : IMultiValueConverter
{
#region IMultiValueConverter Members
public object Convert(object[] values,
Type targetType,
object parameter,
CultureInfo culture)
{
if (values == null || values.Length < 2)
{
throw new ArgumentException(
"HalfValueConverter expects 2 double values to be passed" +
" in this order -> totalWidth, width",
"values");
}
double totalWidth = (double)values[0];
double width = (double)values[1];
return (object)((totalWidth - width) / 2);
}
public object[] ConvertBack(object value,
Type[] targetTypes,
object parameter,
CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
然后用xaml
<DockPanel>
<DockPanel.Resources>
<local:HalfValueConverter x:Key="HalfValue" />
</DockPanel.Resources>
<Canvas x:Name="canvas">
<Ellipse
Height="{Binding ElementName=canvas, Path=ActualHeight, Converter={StaticResource Escalated}}"
Width="{Binding ElementName=canvas, Path=ActualWidth, Converter={StaticResource Escalated}}"
Stroke="Red"
x:Name="ellipse">
<Canvas.Left>
<MultiBinding Converter="{StaticResource HalfValue}">
<Binding ElementName="canvas" Path="ActualWidth" />
<Binding ElementName="ellipse" Path="ActualWidth" />
</MultiBinding>
</Canvas.Left>
<Canvas.Top>
<MultiBinding Converter="{StaticResource HalfValue}">
<Binding ElementName="canvas" Path="ActualHeight" />
<Binding ElementName="ellipse" Path="ActualHeight" />
</MultiBinding>
</Canvas.Top>
</Ellipse>
</Canvas>
</DockPanel>