C# “如何垂直”;中心“;对齐多行文字
对不起,如果标题有点误导,我很难给它命名。它也不完全是“中心”。(更多解释见下文) 嗨,我要做一个项目来写编号的乐谱。但我发现了一个障碍,在平衡“字体”。(请参见下图了解视觉效果)C# “如何垂直”;中心“;对齐多行文字,c#,wpf,user-controls,C#,Wpf,User Controls,对不起,如果标题有点误导,我很难给它命名。它也不完全是“中心”。(更多解释见下文) 嗨,我要做一个项目来写编号的乐谱。但我发现了一个障碍,在平衡“字体”。(请参见下图了解视觉效果) 我需要1234在一条直线上 我使用WrapPanel作为笔记的容器(如屏幕中) 主要问题在于音高点,它位于音符上方或下方。音高绑定到音符,所以我需要在1个用户控件中处理它。但是,如果是这样的话,那么我无法控制注释“字体”的位置在一行中 以下是我的笔记用户控制代码: XAML <UserControl x:Cl
1234
在一条直线上WrapPanel
作为笔记的容器(如屏幕中)<UserControl x:Class="RevisiConverter.NumericNoteBox"
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" Width="{Binding ActualWidth, ElementName=txbNote}"
Height="{Binding ActualHeight, ElementName=mainStack}">
<StackPanel Name="mainStack">
<StackPanel Name="topStack">
</StackPanel>
<Canvas Name="canvas" Width="{Binding ActualWidth, ElementName=txbNote}" Height="{Binding ActualHeight, ElementName=txbNote}"
HorizontalAlignment="Center">
<TextBlock Name="txbNote" Text="1" Foreground="Black" FontSize="15"
Margin="0,0,0,-3" FontFamily="Courier" Canvas.Top="0" Canvas.Left="0"/>
</Canvas>
<StackPanel Name="botStack">
</StackPanel>
</StackPanel>
XAML.CS
public partial class NumericNoteBox : UserControl
{
private Note _child;
private Line _sharp;
public Note Child
{
get { return _child; }
set
{
_child = value;
Update();
}
}
public NumericNoteBox()
{
InitializeComponent();
_sharp = null;
}
public void Update()
{
txbNote.Text = _child.MainNote.ToString();
if (_sharp != null)
{
_sharp.Visibility = Visibility.Hidden;
}
topStack.Children.Clear();
botStack.Children.Clear();
if (_child != null)
{
if (_child.Pitch > 0)
{
for (int i = 0; i < _child.Pitch; i++)
{
topStack.Children.Add(new Ellipse());
(topStack.Children[topStack.Children.Count - 1] as Ellipse).Width = 3;
(topStack.Children[topStack.Children.Count - 1] as Ellipse).Height = 3;
(topStack.Children[topStack.Children.Count - 1] as Ellipse).Fill = Brushes.Black;
if (_child.Accidental != Note.Accidentals.Flat)
{
(topStack.Children[topStack.Children.Count - 1] as Ellipse).Margin = new Thickness(0, 1, 0, 0);
}
else
{
(topStack.Children[topStack.Children.Count - 1] as Ellipse).Margin = new Thickness(8, 1, 0, 0);
}
}
}
else if (_child.Pitch < 0)
{
for (int i = 0; i < Math.Abs(_child.Pitch); i++)
{
botStack.Children.Add(new Ellipse());
(botStack.Children[botStack.Children.Count - 1] as Ellipse).Width = 3;
(botStack.Children[botStack.Children.Count - 1] as Ellipse).Height = 3;
(botStack.Children[botStack.Children.Count - 1] as Ellipse).Fill = Brushes.Black;
if (_child.Accidental != Note.Accidentals.Flat)
{
(botStack.Children[botStack.Children.Count - 1] as Ellipse).Margin = new Thickness(0, 1, 0, 0);
}
else
{
(botStack.Children[botStack.Children.Count - 1] as Ellipse).Margin = new Thickness(8, 1, 0, 0);
}
}
}
if (_child.Accidental == Note.Accidentals.Flat)
{
txbNote.Text = "b" + _child.MainNote.ToString();
}
else if (_child.Accidental == Note.Accidentals.Sharp)
{
if (_sharp == null)
{
_sharp = new Line();
_sharp.X1 = 10;
_sharp.Y1 = 2.5;
_sharp.X2 = -2.5;
_sharp.Y2 = 12.5;
_sharp.StrokeThickness = 1;
_sharp.Stroke = Brushes.Black;
canvas.Children.Add(_sharp);
}
_sharp.Visibility = Visibility.Visible;
}
}
}
}
public分部类NumericNoteBox:UserControl
{
私人票据(儿童);;
私人线路(u sharp),;
公共票据儿童
{
获取{return\u child;}
设置
{
_孩子=价值;
更新();
}
}
公共数字记事本()
{
初始化组件();
_夏普=零;
}
公共无效更新()
{
txbNote.Text=_child.MainNote.ToString();
如果(_sharp!=null)
{
_sharp.Visibility=Visibility.Hidden;
}
topStack.Children.Clear();
botStack.Children.Clear();
如果(_child!=null)
{
如果(_child.Pitch>0)
{
对于(int i=0;i<\u child.Pitch;i++)
{
topStack.Children.Add(新椭圆());
(topStack.Children[topStack.Children.Count-1]作为椭圆)。宽度=3;
(topStack.Children[topStack.Children.Count-1]作为椭圆)。高度=3;
(topStack.Children[topStack.Children.Count-1]为椭圆)。填充=画笔。黑色;
如果(_child.contractive!=Note.acidentals.Flat)
{
(topStack.Children[topStack.Children.Count-1]为椭圆)。边距=新厚度(0,1,0,0);
}
其他的
{
(topStack.Children[topStack.Children.Count-1]为椭圆)。边距=新厚度(8,1,0,0);
}
}
}
否则如果(_child.Pitch<0)
{
for(int i=0;i
注:
您应该使用ItemsControl来执行此操作,该控件为数字注释使用适当的
ItemTemplate
首先,创建一个ViewModel,定义“数字注释”项的集合:
为了可视化音高,我建议使用一个路径
对象,其几何体由许多椭圆几何组成。要实现这一点,您需要实现一个绑定转换器,将节数转换为几何体,如下所示。它使用Convert方法的参数
参数为正螺距值或负螺距值创建几何图形
public class NotePitchConverter : IValueConverter
{
private const double radius = 1.5;
private const double distance = 2 * radius + 1;
public object Convert(
object value, Type targetType, object parameter, CultureInfo culture)
{
var pitch = (int)value;
var geometry = new GeometryGroup();
if (parameter as string == "Bottom")
{
pitch = -pitch;
}
for (int i = 0; i < pitch; i++)
{
geometry.Children.Add(new EllipseGeometry(
new Point(radius, radius + i * distance), radius, radius));
}
return geometry;
}
public object ConvertBack(
object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
并编写如下所示的ItemsControl。请注意,DataTemplate对显示顶部和底部节距的路径元素使用固定高度。如果你需要显示三个以上的点,你需要增加它们的高度
<ItemsControl ItemsSource="{Binding NumericNotes}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="2">
<Grid.RowDefinitions>
<RowDefinition Height="12"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="12"/>
</Grid.RowDefinitions>
<Path Grid.Row="0" Fill="Black" HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Data="{Binding Pitch,
Converter={StaticResource NotePitchConverter}}"/>
<TextBlock Grid.Row="1" Text="{Binding Number}"/>
<Path Grid.Row="2" Fill="Black" HorizontalAlignment="Center"
VerticalAlignment="Top"
Data="{Binding Pitch,
Converter={StaticResource NotePitchConverter},
ConverterParameter=Bottom}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
public class NotePitchConverter : IValueConverter
{
private const double radius = 1.5;
private const double distance = 2 * radius + 1;
public object Convert(
object value, Type targetType, object parameter, CultureInfo culture)
{
var pitch = (int)value;
var geometry = new GeometryGroup();
if (parameter as string == "Bottom")
{
pitch = -pitch;
}
for (int i = 0; i < pitch; i++)
{
geometry.Children.Add(new EllipseGeometry(
new Point(radius, radius + i * distance), radius, radius));
}
return geometry;
}
public object ConvertBack(
object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
<Window.Resources>
<local:NotePitchConverter x:Key="NotePitchConverter"/>
</Window.Resources>
<ItemsControl ItemsSource="{Binding NumericNotes}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="2">
<Grid.RowDefinitions>
<RowDefinition Height="12"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="12"/>
</Grid.RowDefinitions>
<Path Grid.Row="0" Fill="Black" HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Data="{Binding Pitch,
Converter={StaticResource NotePitchConverter}}"/>
<TextBlock Grid.Row="1" Text="{Binding Number}"/>
<Path Grid.Row="2" Fill="Black" HorizontalAlignment="Center"
VerticalAlignment="Top"
Data="{Binding Pitch,
Converter={StaticResource NotePitchConverter},
ConverterParameter=Bottom}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>