对不起,如果标题有点误导,我很难授权。它也不完全是“中心”。 (见下文进一步说明)
嗨,我打算制作一个编写乐谱的项目。但是我找到了平衡“字体”的障碍。 (见下图为视觉)
1 2 3 3 1 2 3 4 4
处于直线“行”WrapPanel
作为笔记的容器(如屏幕中所示)。主要问题在于音高点,它位于音符上方或下方 EITHER 。 Pitch绑定到音符,因此我需要在1个用户控件中处理它。但是,如果是这样,那么我就无法控制音符“font”的位置在一行中。
以下是我的笔记用户控制代码:
XAML
<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;
}
}
}
}
注意:
由于
其他细节:
答案 0 :(得分:2)
您应该使用ItemsControl执行此操作,该控件使用适当的ItemTemplate
作为数字注释。
首先,创建一个定义“数字注释”项集合的ViewModel:
public class NumericNoteItem
{
public int Number { get; set; }
public int Pitch { get; set; }
}
public class ViewModel
{
public ViewModel()
{
NumericNotes = new ObservableCollection<NumericNoteItem>();
}
public ObservableCollection<NumericNoteItem> NumericNotes { get; private set; }
}
在MainWindow的构造函数中,您可以将DataContext设置为此ViewModel的实例,如下所示:
public MainWindow()
{
InitializeComponent();
var vm = new ViewModel();
vm.NumericNotes.Add(new NumericNoteItem { Number = 1, Pitch = 0 });
vm.NumericNotes.Add(new NumericNoteItem { Number = 2, Pitch = 1 });
vm.NumericNotes.Add(new NumericNoteItem { Number = 3, Pitch = -1 });
vm.NumericNotes.Add(new NumericNoteItem { Number = 4, Pitch = 0 });
vm.NumericNotes.Add(new NumericNoteItem { Number = 5, Pitch = 2 });
vm.NumericNotes.Add(new NumericNoteItem { Number = 6, Pitch = -2 });
vm.NumericNotes.Add(new NumericNoteItem { Number = 4, Pitch = 0 });
vm.NumericNotes.Add(new NumericNoteItem { Number = 5, Pitch = 3 });
vm.NumericNotes.Add(new NumericNoteItem { Number = 6, Pitch = -3 });
DataContext = vm;
}
为了可视化音高,我建议使用带有Geometry的Path
对象,该Geometry由许多EllipseGeometries组成。要实现这一点,您需要实现一个绑定转换器,将音高编号转换为几何,如下所示。它使用Convert方法的parameter
参数为正或负音高值创建几何。
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();
}
}
现在,在XAML中,您将在例如XAML中创建此转换器的实例。 MainWindow Resources
:
<Window.Resources>
<local:NotePitchConverter x:Key="NotePitchConverter"/>
</Window.Resources>
并编写ItemsControl,如下所示。请注意,DataTemplate对Path元素使用固定高度,显示顶部和底部音高。如果你需要显示三个以上的点,你需要增加它们的高度。
<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>