Архив рубрики: WPF

Способ поместить null-элемент в ComboBox

В каких случаях может понадобиться включить в коллекцию null? Ну, например, пользователь должен выбрать в ComboBox какой-то из пунктов и один из них должен означать, что выбор сделан не был. В code behind в таком случае мы ждём возврата значения null, а со стороны WPF пускай выглядит как некий пункт “Пусто” или “Нет значения”.

К слову, встречал разные мнения по правомерности такого подхода. Некоторые считают, что null – это отсутствие значения и не должно использоваться. По первому пункту они правы – да это отсутствие значения, по второму – не согласен, null несёт смысловую информацию как раз этого отсутствия значения. Это видится естественным и повсеместно используется в .NET.

С моральной стороной разобрались, перейдём к практической. В чём же сложность такого подхода?

Читать далее

UniformImage: Изменение пропорций картинки без деформации содержимого по краям

В идеальном мире, по версии Microsoft, дизайнеры творят интерфейс в Expression Blend, а программисты пишут бэкенд на C#. В реальности же дизайнеры творят в Photoshop, а программисты ломают голову как вот эту красивую кнопку сконвертировать в XAML, да так чтобы без большого количества костылей. Многие добиваются в этом выдающихся результатов. Стоит только слегка поискать и в сети найдётся куча вариантов, как можно из элементов WPF собрать довольно сложные дизайнерские решения. К сожалению, пару раз так повозившись и оценив затраты по времени понимаешь, что оно того не стоит, проще взять исходный элемент из нарезки как есть, т.е. в виде изображения. И такой вариант, как по мне, является наилучшим с точки зрения продуктивности, однако есть одно НО.

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

Читать далее

Обрезание содержимого Border с закруглёнными краями

Если поместить содержимое внутрь элемента Border и задать закругленные края, то оно всё равно будет вылезать за пределы элемента.
В данном случае, не спасёт даже свойство ClipToBounds, так как оно обрезает содержимое лишь по границам элемента не учитывая закругленных краёв.

Решение проблемы довольно простое. У любого элемента WPF есть свойство OpacityMask, внутри которого можно задать маску непрозрачности элемента. Логично было бы, в нашем случае, задать маску точно такую же как и сам элемент Border. К сожалению, привязать к маске непосредственно оригинальный Border не получится, однако можно просто создать очень похожий Border. Всего лишь надо, чтобы у элементов совпадали свойства CornerRadius, Width и Height, к примеру, через привязку.

В результате, получаем довольно короткое решение средствами XAML:

<Border CornerRadius="30" Background="Green">
    <Border.OpacityMask>
        <VisualBrush>
            <VisualBrush.Visual>
                <Border 
                    Background="Black"
                    CornerRadius="{Binding CornerRadius, RelativeSource={RelativeSource FindAncestor, AncestorType=Border}}"
                    Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType=Border}}"
                    Height="{Binding ActualHeight, RelativeSource={RelativeSource FindAncestor, AncestorType=Border}}"
                    />
            </VisualBrush.Visual>
        </VisualBrush>
    </Border.OpacityMask>
    <TextBlock Text="ТЕКСТ ТЕКСТ ТЕКСТ ТЕКСТ ТЕКСТ ТЕКСТ ТЕКСТ ТЕКСТ ТЕКСТ" />
</Border>

Результат:

WPF: Привязка для свойств отличных от свойств зависимостей

Введение

WPF – замечательная технология, которую, не смотря на все ее недостатки, очень люблю. Тем не менее, часто приходится писать не разметку, а код, который помогает первой работать как надо. Хотелось бы этого избегать и писать чистый XAML, но до сих пор ни одно мое приложение сложнее простого не обходилось без различных хелперов (классов-помощников), написанных на C#. К счастью, есть распространенные случаи, где можно одним хелпером решить сразу группу проблем.

Речь ниже пойдет о привязке в обычных свойствах визуальных элементов, которые не являются свойствами зависимостей (dependecy properties). Штатными средствами WPF этого сделать не получится. Ко всему прочему, мы не можем узнать об изменениях такого свойства, кроме как подписавшись на специальное событие, что противоречит шаблону MVVM. Такие события для каждого свойства могут быть свои. Самый распространенный пример – это PasswordBox и его свойство Password. Так у нас сделать не получится:

<PasswordBox Password={Binding OtherProperty} />

Не будем вдаваться в подробности, зачем разработчики PasswordBox не разрешили привязываться к свойству пароля. Подумаем, что тут можно сделать.

Читать далее