XAML изменить свойство TextBlock Margin на основе размера Rectangle - PullRequest
0 голосов
/ 28 января 2020

Я пытаюсь создать что-то похожее на это:

enter image description here

Это разработано, чтобы быть названием XAML для программного обеспечения VMIX, видео вещания.

Я собираюсь получить много данных из таблицы GS, обработать их в VMIX и назначить эти данные моим текстовым блокам, таким как "Кандидат", "Город" и% голосов.

Из этого%, я хочу, чтобы размер бара увеличивался / уменьшался, мне удалось сделать это частично.

Но главная проблема заключается в том, чтобы поле% TextBlock поместилось справа от прямоугольника. Кто-нибудь знает, как я мог это сделать?

Я никогда не кодировал в C#, у меня есть опыт работы в C, C ++ и JS, поэтому я потратил весь день на поиски этой цели и не смог ее исправить.

Я видел несколько подходящих методов привязки, но я не могу их использовать.

Более того, я работаю над Blend для Visual Studio 2017, и я не понимаю, почему я не могу запустить какой-то простой код при нажатии клавиши F5 ... Это еще одна проблема.

Большое спасибо за вашу помощь.

РЕДАКТИРОВАТЬ:

Я достиг чего-то нового, действительно решение для DIY, но это мое решение lsat если я не могу найти лучше:

У меня будет 2 TextBlock для 1 ProgressBar (Спасибо Крису)

<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>

Так это отлично работает, , но я должен подготовить до того, что мое значение "MarginVotes1" (в GoogleSheet).

Лучше всего было бы прямо в коде сделать что-то вроде этого:

CONVERT Votes1.Text to Int STORE в val

SET x to val + DefaultMargin

CONVERT x to String STORE в MarginX

CREATE String MarginVoteStr as MarginX + ", 500, 0, 0"

SET Votes1.Margin as MarginVoteStr

1 Ответ

0 голосов
/ 01 февраля 2020

Добро пожаловать в WPF. Вот код, который я собрал, чтобы вы были достаточно близки к тому, что вам нужно.

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#:

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;
}

Есть количество точек, которые вы должны отметить:

ItemsControl и DataTemplate

Всякий раз, когда вам нужно отобразить несколько элементов данных в WPF, особенно если число элементов является переменным, вы должны использовать какой-то тип ItemsControl.

ItemsControl берет какую-то коллекцию и отображает каждый элемент, используя DataTemplate. ItemsControl создает новый экземпляр своего ItemTemplate для каждого элемента в своей исходной коллекции. Связь между данными и визуальными объектами устанавливается с помощью привязок данных .

Макет

Все, что находится между тегами <DataTemplate>, представляет собой визуальный макет одного элемента.

Обратите внимание, что я не использую Margin для создания нужного макета. Вместо того, чтобы использовать Margin таким образом, я использую один из WPF со многими Panel элементами управления: Grid. С помощью Grid вы можете определять строки и столбцы как таблицу.

Каждый элемент в моем примере - это Grid с 1 строкой и 3 столбцами. Элементы, составляющие элемент, помещаются в эту сетку с использованием свойства Grid.Column. Каждый столбец имеет Width="Auto", что означает, что он будет расти в соответствии с шириной содержимого внутри. IsSharedSizeScope и SharedSizeGroup делают так, чтобы Grid s каждого отдельного элемента имели одинаковую ширину для первого столбца.

Candidate class

Это класс это будет использоваться для хранения и представления отображаемых данных. Обратите внимание, что имена свойств совпадают со значениями {Binding ______} из DataTemplate.

. В моем главном окне примера содержится коллекция Candidate объектов, хранящихся в свойстве зависимости . Это свойство привязано к ItemsSource из ItemsControl.

Всего

Идея состоит в том, чтобы заполнить вашу коллекцию любыми необходимыми элементами данных и позволить ItemsControl позаботиться о остальное, таким образом сохраняя данные и визуальные элементы проекта относительно независимыми. Даже небольшие визуальные аспекты, такие как правильное форматирование процентного значения для отображения, можно выполнить с помощью DataTemplate вместо записи кода в C#, как показано с использованием StringFormat=P.

...