WPF "Частичные формы" - PullRequest
       8

WPF "Частичные формы"

0 голосов
/ 19 февраля 2011

Я делаю заявку на миграцию БД.Я сделал многопоточный фреймворк с WPF GUI.Я помещаю что-то вроде этого в мое пространство имен / папку:

class Something : Migrator {
    public override Run(){
        //I would need this
        string valueOfMyCustomFieldOnForm = xyz.Text; //example

        int count = 500;
        for(int i = 0; i < 500; i++){
            //do something here
            OnProgressChanged(...); //call event, GUI is updated
        }
        OnCompleted(...); //migration completed
    }
}

Затем, используя отражение, я помещаю все классы в этом пространстве имен в выпадающий список.Когда я выбираю один из списка и нажимаю «Пуск», запускается метод «Поток с кодом в Run».

DB Host: TEXTBOX
DB Username: TEXTBOX
DB Password: TEXTBOX
--
Migrator custom field 1: TEXTBOX
Migrator custom field 2: TEXTBOX
...
--
List with migrated items - irrelevant

В графическом интерфейсе есть несколько общих полей (например, хост базы данных, имя пользователя и т. Д.)Но для некоторых из этих мигрантов мне понадобятся настраиваемые поля в графическом интерфейсе (например, 3 дополнительных поля текстового поля).Каков наилучший способ сделать это в WPF?Мне нужна часть графического интерфейса, чтобы быть динамическим.

1 Ответ

2 голосов
/ 20 февраля 2011

В вашем вопросе много, казалось бы, не относящейся к делу информации, которая, как мне кажется, действительно касается механизмов создания управляемых метаданными пользовательских интерфейсов в WPF.Вот способ решения этой проблемы:

Предположим, что вы хотите создать пользовательский интерфейс, похожий на лист свойств: сетка, отображающая строку для каждого свойства, с подсказкой и элементом управления вводом некоторого вида.Для этого вам понадобится коллекция объектов, каждый элемент которой содержит свойства, которые описывают свойство и его значение.Простой дизайн - это класс, который предоставляет свойство Prompt и свойство Value и реализует уведомление об изменении.

После создания и заполнения этой коллекции вы можете реализовать ItemsControl, отображающийэто в сетке:

<ItemsControl ItemsSource="{Binding Properties}" Grid.IsSharedSizeScope="True">
   <ItemsControl.ItemTemplate>
      <DataTemplate DataType="PropertyViewModel">
         <Grid>
            <Grid.ColumnDefinitions>
               <ColumnDefinition SharedSizeGroup="Prompt"/>
               <ColumnDefinition SharedSizeGroup="Value"/>                   
            </Grid.ColumnDefinition>
            <Grid.RowDefinitions>
               <RowDefinition/>
            </Grid.RowDefinitions>
         </Grid>
         <Label Content="{Binding Prompt}"/>
         <TextBox Grid.Column="1" Text="{Binding Value, Mode=TwoWay}"/>
      </DataTemplate>
   </ItemsControl.ItemTemplate>
</ItemsControl>

Это довольно просто - самое сложное в этом заключается в использовании Grid.IsSharedSizeScope, чтобы все сетки, создаваемые этим элементом управления, использовали одинаковую ширину столбцов.Вы также можете использовать ListView вместо ItemsControl, хотя использование ListView для этого создает кучу проблем, связанных с фокусом и выбором, с которыми вам, возможно, не захочется иметь дело.

Обратите внимание, что, посколькуиз магии, связанной с сопоставлением шаблонов WPF, вы могли бы реализовать свойство Value как object и создавать различные шаблоны для обработки различных возможных типов свойства Value - так же, как это делает лист реальной собственности.Для этого вы должны создать шаблон для каждого типа, например:

<DataTemplate DataType="{x:Type System:String}">
   <TextBox Text="{Binding Value, Mode=TwoWay}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type System:DateTime}">
   <DatePicker Value="{Binding Value, Mode=TwoWay}"/>
</DataTemplate>

и т. Д.Затем вы измените шаблон для PropertyViewModel, чтобы вместо отображения Value в TextBox он использовал ContentPresenter, например:

<ContentPresenter Grid.Column="1" Content="{Binding}"/>
...