为什么 MultiBinding a TranslateTransform.X 在 WPF 中似乎不起作用?
我希望我问这个问题不是愚蠢的,但我正在尝试在 WPF 中设计一个图形查看器,作为框架中的一个完全的新手;尽管我确实针对我的问题提出了一些解决方案,但我最引以为傲的一个……却没有发挥应有的作用。我想做的是将一个节点放置在 ItemsControl 上我用 Dijkstra 的 alg + 一些数学计算出的位置。问题是,当使用正常的 X 和 Y 绑定时,我移动的是带有边框的 TextBlock 的左上角,但我想要操作的是它们的中心。因此,我的节点最终会从我指定的点开始向右下方移动,而不是以其为中心。
我最终决定使用 NodeViewModel 的 X/Y 属性和网格的 ActualWidth/Height 进行多重绑定。发生的情况是我的所有节点都被放置在(0,0)!我什至调试了代码并查看了转换器,但返回值似乎没问题。我什至尝试了一些随机的事情,例如绑定到其他属性等。
我完全感到困惑。
那么一个问题是——MultiBinding 是这样工作的吗?或者我犯了一些愚蠢的错误?我将在 XAML 代码下方发布我的转换器。 XAML 中删除的部分是工具提示和嵌入的 ItemsControl,但删除这些部分不会改变任何内容(除了提高代码的清晰度)。转换器中的铸造是因为直接铸造到浮动对我来说不起作用(但这无关紧要 - 即使它不是很漂亮,它也会按原样工作)。
另一个问题是 - 我可以用更简单的方式来做吗?喜欢直接操作 TextBlock 的中心吗?
XAML:
<Grid>
<ItemsControl ItemsSource="{Binding Source={StaticResource Nodes}, Path=Nodes}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vievModels:NodeViewModel">
<Grid>
<Grid x:Name="nodeGrid">
<Grid.RenderTransform>
<TranslateTransform>
<TranslateTransform.X>
<MultiBinding Converter="{StaticResource PositionConverter}">
<Binding Path="Position.X"/>
<Binding ElementName="nodeGrid" Path="ActualWidth"/>
</MultiBinding>
</TranslateTransform.X>
<TranslateTransform.Y>
<MultiBinding Converter="{StaticResource PositionConverter}">
<Binding Path="Position.Y"/>
<Binding ElementName="nodeGrid" Path="ActualHeight"/>
</MultiBinding>
</TranslateTransform.Y>
</TranslateTransform>
</Grid.RenderTransform>
<Border BorderBrush="Black" BorderThickness="2" CornerRadius="7">
<Border.Background>
<SolidColorBrush Color="{Binding Color}" Opacity="0.5"/>
</Border.Background>
<TextBlock x:Name="Label" Margin="5,5,5,5" MaxWidth="160" TextAlignment="Center" TextWrapping="Wrap" FontFamily="Lucida Console" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding Path=Label}"/>
</Border>
...
</Grid>
...
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Transparent"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
C#:
public class PositionConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
float point = float.Parse(values[0].ToString());
float size = float.Parse(values[1].ToString());
return point - size / 2;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
干杯, 迈克尔
I hope I am not being silly asking this, but I am trying to design a graph viewer in WPF being a total newb in the framework; although I did come up with a couple of solutions to my problems, the one I'm most proud of... does not work where it should. What I'm trying to do is to place a node on the ItemsControl at a position I calculated with Dijkstra's alg + some maths. The problem is that what I move around when using a normal X and Y Binding is the upper-left corner of the TextBlock with Border but what I'd like to manpulate is their center instead. Thus, my nodes end up sticking down and to the right from the point I specify, not centered on it.
I finally settled for a Multibinding using the X/Y property of my NodeViewModel and the Grid's ActualWidth/Height. What happens is that all my nodes get placed at (0,0)! I even debugged the code and looked at the converter, but the return value seems OK. I even tried some random things like binding to other properties etc.
I am totally puzzled.
So one question would be - does MultiBinding work that way? Or am I making some stupid mistake? I'll post my Converter below the XAML code. The parts in XAML cut out are a tooltip and an embedded ItemsControl, but cutting these out changes nothing (except for improving the clarity of the code). The casting in the converter is because casting directly to float does not work for me (but that's irrelevat - it works the way it is even if it's not very beautiful).
And another question would be - can I do it in any simpler way? Like manipulate the center of the TextBlock directly?
XAML:
<Grid>
<ItemsControl ItemsSource="{Binding Source={StaticResource Nodes}, Path=Nodes}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vievModels:NodeViewModel">
<Grid>
<Grid x:Name="nodeGrid">
<Grid.RenderTransform>
<TranslateTransform>
<TranslateTransform.X>
<MultiBinding Converter="{StaticResource PositionConverter}">
<Binding Path="Position.X"/>
<Binding ElementName="nodeGrid" Path="ActualWidth"/>
</MultiBinding>
</TranslateTransform.X>
<TranslateTransform.Y>
<MultiBinding Converter="{StaticResource PositionConverter}">
<Binding Path="Position.Y"/>
<Binding ElementName="nodeGrid" Path="ActualHeight"/>
</MultiBinding>
</TranslateTransform.Y>
</TranslateTransform>
</Grid.RenderTransform>
<Border BorderBrush="Black" BorderThickness="2" CornerRadius="7">
<Border.Background>
<SolidColorBrush Color="{Binding Color}" Opacity="0.5"/>
</Border.Background>
<TextBlock x:Name="Label" Margin="5,5,5,5" MaxWidth="160" TextAlignment="Center" TextWrapping="Wrap" FontFamily="Lucida Console" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding Path=Label}"/>
</Border>
...
</Grid>
...
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Transparent"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
C#:
public class PositionConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
float point = float.Parse(values[0].ToString());
float size = float.Parse(values[1].ToString());
return point - size / 2;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Cheers,
Michael
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
正如我所想 - 一个愚蠢的错误。转换后的属性具有双精度,并且不能为其分配浮点数。我必须学习如何打开调试输出才能看到这一点。
Just as I thought - a silly mistake. The converted property is of double precision and cannot have float assigned to it. I had to learn how to turn on the debug output to see that.
如果您在网格上设置 RenderTransformOrigin=".5,.5",它应该与原始值的绑定一起使用。
If you set RenderTransformOrigin=".5,.5" on the Grid, it should work with a binding to your original values.