Программно добавьте средства управления к форме WPF

Использование mtext для получения меток глобальной оси - хорошая идея. Вы также можете сделать это с легендой. Для меток тиков я бы рекомендовал повернуть их на 90 °. Следовательно, общая читаемость должна была улучшиться. (Может быть даже более точно настроено, чем мое решение.)

Сначала мы помещаем матрицы в список и используем barplot в lapply для сохранения ввода.

L <- list(mxCarabooda=mxCarabooda, mxNeerabup=mxNeerabup, mxNowergup=mxNeerabup)

В опции par мы включаем oma, чтобы увеличить внешние поля, и xpd, чтобы разместить текст и легенды где угодно. В barplot мы отключаем ось x и добавляем их вручную. Используйте сжатие без потерь , установив compression="lzw".

tiff("barplot.tiff", width=260, height=100, units='mm', res=300, compression="lzw")
par(mfrow=c(1,3), mar=c(5, 4, 4, 2) + 0.1, oma=c(6, 4, 0, 0), xpd=TRUE)

lapply(seq_along(L), function(x) {
  b1 <- barplot(L[[x]], main=gsub("^mx", "", names(L)[x]), beside=TRUE, xaxt="n",
                col=c("gray63","gray87"), ylim=c(0,30))
  axis(1, at=apply(b1, 2, mean), labels=colnames(L[[x]]), 
       tick=FALSE, line=FALSE, las=2)
})

mtext('Change in water table at each level of GW cut', side=1, outer=TRUE, line=1)  # x-lab
mtext('Profit loss ($m)', side=2, outer=TRUE, line=1)                               # y-lab
legend(-16.5, -15, bty="n", legend=c('Loss in GM','Loss in adjusted GM'), 
       col=c("gray63","gray87"), cex=1.2, pch=15, horiz=TRUE, xpd=NA)           

dev.off()

Результат

enter image description here

[1124]

Однако, чтобы решение работало Я должен был как минимум удвоить размер tiff, потому что поля рисунка становятся слишком большими. Тем не менее, соотношение сторон остается тем же, что должно быть более важным . Не могли бы вы проверить это в своем журнале? Возможно, вы могли бы также использовать pdf("barplot.pdf", width=13, height=5) вместо строки tiff(.).

Данные

mxCarabooda <- structure(c(13.47258, 7.430879, 13.47151, 7.53012, 14.83685, 
                           8.940968, 15.37691, 9.617533), .Dim = c(2L, 4L), .Dimnames = list(
                             c("ChangeNP", "ChangeNP.1"), c("Sl-2 0.1", "S2-3 0.055", 
                                                            "S3-4 0.056", "S4-5 0.056")))
mxNeerabup <- structure(c(3.499426, 2.232676, 3.499596, 2.239664, 3.836086, 
                          2.566649, 3.995115, 2.725839), .Dim = c(2L, 4L), .Dimnames = list(
                            c("ChangeNP", "ChangeNP.1"), c("Sl-2 0.1", "S2-3 0.055", 
                                                           "S3-4 0.056", "S4-5 0.056")))

mxNowergup <- structure(c(3.5135, 1.700544, 3.513586, 1.710387, 3.850266, 2.034689, 
                          4.009113, 2.194351), .Dim = c(2L, 4L), .Dimnames = list(
                            c("ChangeNP", "ChangeNP.1"), c("Sl-2 0.02", "S2-3 0.01", 
                                                           "S3-4 0.02", "S4-5 0.02")))

26
задан Ilmari Karonen 13 March 2016 в 16:24
поделиться

3 ответа

1114 Ладно, во второй раз прелесть. Основываясь на скриншоте макета, я сразу могу сделать вывод, что вам нужна WrapPanel панель макета, которая позволяет элементам заполняться до тех пор, пока не достигнет края, после чего оставшиеся элементы переходят на следующую строку. Но вы все еще хотите использовать ItemsControl, чтобы получить все преимущества привязки данных и динамической генерации. Поэтому для этого мы будем использовать свойство ItemsControl.ItemsPanel, которое позволяет нам указать панель, в которую будут помещены элементы. Давайте снова начнем с выделенного кода:

public partial class Window1 : Window
{
    public ObservableCollection<Field> Fields { get; set; }

    public Window1()
    {
        InitializeComponent();

        Fields = new ObservableCollection<Field>();
        Fields.Add(new Field() { Name = "Username", Length = 100, Required = true });
        Fields.Add(new Field() { Name = "Password", Length = 80, Required = true });
        Fields.Add(new Field() { Name = "City", Length = 100, Required = false });
        Fields.Add(new Field() { Name = "State", Length = 40, Required = false });
        Fields.Add(new Field() { Name = "Zipcode", Length = 60, Required = false });

        FieldsListBox.ItemsSource = Fields;
    }
}

public class Field
{
    public string Name { get; set; }
    public int Length { get; set; }
    public bool Required { get; set; }
}

Здесь мало что изменилось, но я отредактировал примеры полей, чтобы лучше соответствовать вашему примеру. Теперь давайте посмотрим, где происходит магия - XAML для Window:

<Window x:Class="DataBoundFields.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DataBoundFields"
Title="Window1" Height="200" Width="300">
<Window.Resources>
    <local:BoolToVisibilityConverter x:Key="BoolToVisConverter"/>
</Window.Resources>
<Grid>
    <ListBox x:Name="FieldsListBox">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <Label Content="{Binding Name}" VerticalAlignment="Center"/>
                    <TextBox Width="{Binding Length}" Margin="5,0,0,0"/>
                    <Label Content="*" Visibility="{Binding Required, Converter={StaticResource BoolToVisConverter}}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel Orientation="Horizontal" 
                           Height="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=ActualHeight}"
                           Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=ActualWidth}"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>
</Grid>

Во-первых, вы заметите, что ItemTemplate немного изменился. Метка по-прежнему привязана к свойству name, но теперь ширина текстового поля привязана к свойству length (поэтому вы можете иметь текстовые поля различной длины). Кроме того, я добавил «*» во все обязательные поля, используя упрощенный BoolToVisibilityConverter (код которого вы можете найти где угодно, и я не буду публиковать здесь).

Главное, на что стоит обратить внимание - это использование WrapPanel в свойстве ItemsPanel нашего ListBox. Это говорит ListBox, что любые элементы, которые он генерирует, должны быть помещены в горизонтальный свернутый макет (это соответствует вашему скриншоту). Что делает эту работу еще лучше, так это привязка к высоте и ширине на панели - это говорит о том, что «сделайте эту панель того же размера, что и мое родительское окно». Это означает, что когда я изменяю размер Window, WrapPanel соответствующим образом корректирует его размер, что приводит к лучшей компоновке элементов.

24
ответ дан DaveInCaz 28 November 2019 в 07:08
поделиться

Не рекомендуется добавлять подобные элементы управления. В WPF вы в идеале должны поместить ListBox (или ItemsControl) и связать свою коллекцию бизнес-объектов как свойство itemsControl.ItemsSource. Теперь определите DataTemplate в XAML для вашего типа DataObject, и все готово. В этом волшебство WPF.

Люди, происходящие из прошлого, имеют тенденцию поступать так, как вы описали, а это неправильно в WPF.

17
ответ дан Jobi Joy 28 November 2019 в 07:08
поделиться

Я бы послушал ответы Чарли и Джоби, но для того, чтобы прямо ответить на вопрос ... (Как добавить элементы управления и расположить их вручную.)

Используйте элемент управления Canvas вместо а Grid. Холсты дают элемент управления бесконечное количество места, и позволяют размещать их вручную. Он использует вложенные свойства для отслеживания положения. В коде это будет выглядеть так:

var tb = new TextBox();
myCanvas.Children.Add(tb);
tb.Width = 100;
Canvas.SetLeft(tb, 50);
Canvas.SetTop(tb, 20);

В XAML ...

<Canvas>
  <TextBox Width="100" Canvas.Left="50" Canvas.Top="20" />
</Canvas>

Вы также можете расположить их относительно правого и нижнего края. При указании вершины и низа элемент управления будет изменен по вертикали с помощью Canvas. Аналогично для левых и правых.

8
ответ дан Miquella 28 November 2019 в 07:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: