Как создать общий базовый стиль окна WPF? - PullRequest
3 голосов
/ 22 сентября 2011

Есть ли какой-нибудь рекомендуемый способ с WPF создать общий стиль окна для использования в приложении?У меня есть несколько диалоговых окон, которые появляются в моем приложении, и я хотел бы, чтобы все они были стилизованы одинаково (одна и та же граница окна, положение кнопки «ОК / Отмена» и т. Д.) И просто имели различное «содержимое» в каждом, в зависимости от ситуации.Итак, в одном диалоговом окне может быть поле со списком, в другом может быть текстовое поле и т. Д.

Я понимаю, как сделать базовые файлы .cs usercontrol, но я не могу на всю жизнь работатьхороший способ создать единое окно, которое может содержать различный контент при запуске?

Ура, рДж

Ответы [ 5 ]

16 голосов
/ 22 сентября 2011

Одним из способов сделать это будет новый пользовательский элемент управления, назовем его DialogShell:

namespace Test.Dialogs
{
    public class DialogShell : Window
    {
        static DialogShell()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(DialogShell), new FrameworkPropertyMetadata(typeof(DialogShell)));
        }
    }
}

Теперь нужен шаблон, который обычно определяется в Themes/Generic.xaml, там вы можете создать структуру по умолчанию и связать Content:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Test.Dialogs">
    <Style TargetType="{x:Type local:DialogShell}" BasedOn="{StaticResource {x:Type Window}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:DialogShell}">
                    <Grid Background="{TemplateBinding Background}">
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <!-- This ContentPresenter automatically binds to the Content of the Window -->
                        <ContentPresenter />
                        <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="5" HorizontalAlignment="Right">
                            <Button Width="100" Content="OK" IsDefault="True" />
                            <Button Width="100" Content="Cancel" IsCancel="True" />
                        </StackPanel>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Это всего лишь пример, вы, вероятно, хотите соединить эти кнопки с пользовательскими событиями и свойствами, которые необходимо определить в cs-файле.

Эту оболочку затем можно использовать так:

<diag:DialogShell x:Class="Test.Dialogs.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:diag="clr-namespace:Test.Dialogs"
        Title="Window1" Height="300" Width="300">
    <Grid>
        <TextBlock Text="Lorem Ipsum" />
    </Grid>
</diag:DialogShell>
namespace Test.Dialogs
{
    public partial class Window1 : DialogShell
    {
        public Window1()
        {
            InitializeComponent();
        }
    }
}

Пример подключения событий (хотя не уверен, что это «правильный» подход)

<Button Name="PART_OKButton" Width="100" Content="OK" IsDefault="True" />
<Button Name="PART_CancelButton" Width="100" Content="Cancel" IsCancel="True" />
namespace Test.Dialogs
{
    [TemplatePart(Name = "PART_OKButton", Type = typeof(Button))]
    [TemplatePart(Name = "PART_CancelButton", Type = typeof(Button))]
    public class DialogShell : Window
    {
        //...

        public DialogShell()
        {
            Loaded += (_, __) =>
                {
                    var okButton = (Button)Template.FindName("PART_OKButton", this);
                    var cancelButton = (Button)Template.FindName("PART_CancelButton", this);
                    okButton.Click += (s, e) => DialogResult = true;
                    cancelButton.Click += (s, e) => DialogResult = false;
                };
        }
    }
}
2 голосов
/ 01 июня 2012

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

    public DataEntryBase()
    {
        Loaded += (_, __) =>
        {
            var saveButton = (Button)Template.FindName("PART_SaveAndCloseButton", this);
            var cancelButton = (Button)Template.FindName("PART_CancelButton", this);
            saveButton.Click += SaveAndClose_Click;
            cancelButton.Click += Cancel_Click;
        };
    }

    protected virtual void SaveAndClose_Click(object sender, RoutedEventArgs e) { DialogResult = true; }

    protected virtual void Cancel_Click(object sender, RoutedEventArgs e) { }

Функция сохранения затем переопределяется в каждом производном классе для сохранения конкретной сущности:

    protected override void SaveAndClose_Click(object sender, RoutedEventArgs e)
    {
        if (Save())
        {
            base.SaveAndClose_Click(sender, e);
        }
    }

    private bool Save()
    {
        Contact item = contactController.SaveAndReturnContact((Contact)DataContext);
        if (item!=null) 
        {
            DataContext = item;
            return true; }
        else 
        {
            MessageBox.Show("The contact was not saved, something bad happened :(");
            return false;
        }            
    }
0 голосов
/ 24 июля 2014

Создайте шаблон формы Xaml и добавьте шаблон в каталог VS Installed ItemTemplates.

1) создайте файл wpf xaml и xaml.cs, в котором все необходимые компоненты, необходимые для новой формы, добавлены в ваш файл.приложение.В моем случае я хотел, чтобы кнопки заголовка и панели инструментов.

2) тестировали новые файлы xaml в текущем системном потоке.

3) копировали xaml / xaml.cs во временную папку и переименовывали обаимена файлов, которые вы хотите, чтобы их распознавали как хорошее имя шаблона.a) Измените первую строку в файле xaml на - Window x: Class = "$ rootnamespace $. $ safeitemname $"

b) Внесите 3 изменения в файл xaml.cs, чтобы новое имя было скопировано, когдаиспользуя шаблон - пространство имен $ rootnamespace $ (// имя динамического пространства имен) - открытый частичный класс $ safeitemname $ (// имя динамического класса) - открытый $ safeitemname $ () (// имя динамического конструктора)

4) Теперь создайте файл vstemplate: т.е.MyTemplate.vstemplate со следующим содержимым:

<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Item">
  <TemplateData>
    <DefaultName>WpfFormTemplate.xaml</DefaultName>
    <Name>WpfFormTemplate</Name>
    <Description>Wpf/Entities form</Description>
    <ProjectType>CSharp</ProjectType>
    <SortOrder>10</SortOrder>
    <Icon>Logo.ico</Icon>
  </TemplateData>
  <TemplateContent>
    <References>
        <Reference>
            <Assembly>System.Windows.Forms</Assembly>
        </Reference>
        <Reference>
            <Assembly>Workplace.Data.EntitiesModel</Assembly>
        </Reference>
        <Reference>
            <Assembly>Workplace.Forms.MainFormAssemb</Assembly>
        </Reference>
    </References>
    <ProjectItem SubType="Designer" TargetFileName="$fileinputname$.xaml" ReplaceParameters="true">WpfFormTemplate.xaml</ProjectItem>
    <ProjectItem SubType="Code" TargetFileName="$fileinputname$.xaml.cs" ReplaceParameters="true">WpfFormTemplate.xaml.cs</ProjectItem>
  </TemplateContent>
</VSTemplate>

5) Получив все эти файлы, заархивируйте файлы и поместите zip-файл в .... \ Documents \ Visual Studio 2012 \ Templates \ ItemTemplates\ WPF каталог.Теперь вы можете зайти в VS2012 и использовать функцию ADD \ New, чтобы увидеть шаблон, выбрать и переименовать, как в обычном процессе.Шаблон можно использовать таким же образом для VS2010, поместив файл zip в каталог Wpf шаблонов 2010 года.

Файл логотипа также должен быть включен в файл zip, или если у вас нет файлазатем удалите эту строку из файла MyTemplate.vstemplate.

0 голосов
/ 28 октября 2013

Создание объекта cusotm, который является производным от класса окна ..

http://maffelu.net/wpf-window-inheritance-problems-and-problems/

0 голосов
/ 22 сентября 2011

Вы можете использовать определение стиля в App.Xaml, которое предназначено для всех окон.

Это пример того, как может выглядеть ваш App.Xaml:

<Application x:Class="ES.UX.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         StartupUri="Views/MainWindow.xaml">
<Application.Resources>
    <Style TargetType="Window">
        <Setter Property="WindowStyle" Value="ToolWindow" />
    </Style>
</Application.Resources>

Тогда для более сложных сценариев вам может понадобиться установить ControlTemplate для вашего окна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...