简体   繁体   English

XAML 根据矩形的大小更改 TextBlock Margin 属性

[英]XAML change TextBlock Margin property based on Rectangle's size

I'm trying to create something looking like this :我正在尝试创建看起来像这样的东西:

在此处输入图片说明

It's designed to be an XAML title for VMIX software, video broadcasting purposes.它被设计为用于 VMIX 软件和视频广播的 XAML 标题。

I'm gonna get a lot of datas from a GSheet, handle in VMIX, and assign those datas to my TextBlocks such as "Candidate", "City" and the Votes %.我将从 GSheet 中获取大量数据,在 VMIX 中处理,并将这些数据分配给我的 TextBlock,例如“候选人”、“城市”和投票百分比。

From that % I want the bar size to increase/decrease, I managed to do part of that.从那个百分比我希望条形尺寸增加/减少,我设法做到了其中的一部分。

But the main issue is to get the % TextBlock margin to fit on the right of the rectangle.但主要问题是让 % TextBlock 边距适合矩形的右侧。 Anyone knows how I could do that ?任何人都知道我怎么能做到这一点?

I have never been coding in C#, I have a background in C, C++ and JS, so I've spent my day looking for that purpose and couldn't make it right.我从来没有用 C# 编码,我有 C、C++ 和 JS 的背景,所以我花了一整天的时间寻找这个目的,但没能做到。

I saw some binding methods that could fit, but I'm unable to use them.我看到了一些适合的绑定方法,但我无法使用它们。

Moreover I'm working on Blend for Visual Studio 2017, and I don't get why I can't run some simple code on it when pressing F5... It's another problem thought.此外,我正在为 Visual Studio 2017 开发 Blend,我不明白为什么按 F5 时我不能在上面运行一些简单的代码......这是另一个问题。

Thanks a lot for your help.非常感谢你的帮助。

EDIT :编辑 :

I've reached something new so far, really DIY solution but it's my lsat solution if I can't find better :到目前为止,我已经找到了一些新的东西,真正的 DIY 解决方案,但如果我找不到更好的解决方案,那就是我的 lsat 解决方案:

I'll have 2 TextBlock for 1 ProgressBar (Thanks to Chris)我将有 2 个 TextBlock 用于 1 个 ProgressBar(感谢 Chris)

<Grid Margin="0,0,-8,0">
    <TextBlock x:Name="Votes1" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Margin="{Binding Text, ElementName=MarginVotes1}" FontSize="72" Width="853" Height="188"><Run Text="6"/><Run Text="00"/></TextBlock>
    <ProgressBar HorizontalAlignment="Left" Height="79" Margin="171,503,0,0" VerticalAlignment="Top" Width="{Binding Path=Text, ElementName=Votes1}" Background="#FFEA4545"/>
    <TextBlock x:Name="MarginVotes1" HorizontalAlignment="Left" Margin="171,587,0,0" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="72" Height="98" Width="550"><Run Text="8"/><Run Text="0"/><Run Text="0"/><Run Text=","/><Run Text="4"/><Run Text="9"/><Run Text="0"/><Run Text=",0,0"/> 
   </TextBlock>

So this works fine, but I have to prepare before what my "MarginVotes1" value is (in GoogleSheet).所以这很好用,但我必须在我的“MarginVotes1”值(在 GoogleSheet 中)之前做好准备

The best would be directly in code behind to do something like this :最好是直接在后面的代码中做这样的事情:

CONVERT Votes1.Text to Int STORE in val在 val 中将 Votes1.Text 转换为 Int STORE

SET x to val + DefaultMargin将 x 设置为 val + DefaultMargin

CONVERT x to String STORE in MarginX在 MarginX 中将 x 转换为字符串 STORE

CREATE String MarginVoteStr as MarginX + ",500, 0, 0"创建字符串 MarginVoteStr 作为 MarginX + ",500, 0, 0"

SET Votes1.Margin as MarginVoteStr将 Votes1.Margin 设置为 MarginVoteStr

Welcome to WPF.欢迎来到 WPF。 Here's some code I put together that you should be pretty close to what you need.这是我整理的一些代码,您应该非常接近您的需要。

XAML: XAML:

<ItemsControl Grid.IsSharedSizeScope="True" ItemsSource="{Binding Candidates}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid HorizontalAlignment="Left">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition SharedSizeGroup="Candidate" Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>

                <TextBlock Text="{Binding Name}"/>
                <Rectangle Grid.Column="1" Height="10" Margin="5, 0" Width="{Binding BarWidth}" Fill="{Binding BarColor}"/>
                <TextBlock Grid.Column="2" Text="{Binding Percentage, StringFormat=P}"/>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

C#: C#:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Candidates = new List<Candidate> { new Candidate { Name = "Joe", Percentage = .50, BarColor = Brushes.Green},
                                            new Candidate { Name = "Bob", Percentage = .30, BarColor = Brushes.Yellow},
                                            new Candidate { Name = "Sarah", Percentage = .20, BarColor = Brushes.Gray}};
    }
               
    public List<Candidate> Candidates
    {
        get { return (List<Candidate>)GetValue(CandidatesProperty); }
        set { SetValue(CandidatesProperty, value); }
    }
    public static readonly DependencyProperty CandidatesProperty =
        DependencyProperty.Register("Candidates", typeof(List<Candidate>), typeof(MainWindow));
}

public class Candidate
{
    public string Name { get; set; }
    public double Percentage { get; set; }
    public Brush BarColor { get; set; }

    //This is just shorter syntax for a readonly property.
    //The multiplier (200) should be whatever length you want a full bar to be
    public double BarWidth => Percentage * 200;
}

There are a number of points you should note:您应该注意以下几点:

ItemsControl and DataTemplate ItemsControl 和 DataTemplate

Whenever you need to display multiple data items in WPF, especially if the number of items is variable, you should be using some type of ItemsControl .每当您需要在 WPF 中显示多个数据项时,尤其是在项数可变的情况下,您应该使用某种类型的ItemsControl

An ItemsControl takes a collection of some kind and displays each item using a DataTemplate . ItemsControl接受某种集合并使用DataTemplate显示每个项目。 An ItemsControl creates a new instance of its ItemTemplate for every item in its source collection. ItemsControl为其源集合中的每个项目创建其ItemTemplate的新实例。 The link between the data and the visuals is established through data bindings .数据和视觉对象之间的链接是通过数据绑定建立的。

Layout布局

Everything between the <DataTemplate> tags is the visual layout of a single item. <DataTemplate>标记之间的所有内容都是单个项目的视觉布局。

Notice that I am not using Margin to create the desired layout.请注意,我没有使用Margin创建所需的布局。 Instead of using Margin in that way, I'm using one of WPFs many Panel controls: Grid .我没有以这种方式使用Margin ,而是使用了 WPF 的许多Panel控件之一: Grid With Grid you can define rows and columns like a table.使用Grid您可以像表格一样定义行和列。

Each item in my example is a Grid with 1 row and 3 columns.我的示例中的每个项目都是一个 1 行 3 列的Grid The elements that make up the item are placed in that grid using the Grid.Column property.构成项目的元素使用Grid.Column属性放置在该网格中。 Each column has Width="Auto" , which means it will grow to accommodate the width of what's inside.每列都有Width="Auto" ,这意味着它将增长以适应内部内容的宽度。 IsSharedSizeScope and SharedSizeGroup make it so that the Grid s of each individual item all have the same width for the first column. IsSharedSizeScopeSharedSizeGroup使每个单独项目的Grid都具有第一列的相同宽度。

Candidate class Candidate

This is the class that will be used to store and represent the data being displayed.这是将用于存储和表示正在显示的数据的类。 Note that the property names match the {Binding ______} values from the DataTemplate .请注意,属性名称与DataTemplate中的{Binding ______}值匹配。

My example main window has a collection of Candidate objects stored in a dependency property .我的示例主窗口有一组Candidate对象存储在一个依赖属性中 This property is bound to the ItemsSource of the ItemsControl .此属性绑定到ItemsControlItemsSource

Overall总体

The idea is to populate your collection with whatever data items you need and let the ItemsControl take care of the rest, thus keeping the data and visuals of the project relatively independent.这个想法是用你需要的任何数据项填充你的集合,让ItemsControl处理其余的事情,从而使项目的数据和视觉效果保持相对独立。 Even small visual aspects like formatting the percentage value correctly for display can be done using the DataTemplate instead of writing the code in C#, as shown using StringFormat=P .即使是小的视觉方面,如正确格式化百分比值以供显示,也可以使用DataTemplate来完成,而不是在 C# 中编写代码,如使用StringFormat=P所示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM