У меня есть элемент управления, который пользователь создает в меню настроек. Я собираюсь дать им возможность либо загрузить изображение в качестве фона элемента управления, либо установить цвета фона. Как я могу позволить пользователю переключать эту функцию, не создавая полностью новый элемент управления или не создавая двух родительских сеток с переключенной видимостью (что удвоило бы страницу xaml)?
Вот файл xaml. Когда я вручную комментирую один из тегов Grid.Background, я могу переключаться между цветами и изображениями. Как мне сделать это программно?
<Grid Name = "myGrid">
<Grid.Background>
<ImageBrush ImageSource = "c:/sports.jpeg" Stretch = "UniformToFill"/>
</Grid.Background>
<Grid.Background>
<LinearGradientBrush StartPoint = "0,1" EndPoint = "0,.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color = "{Binding ColorsBo.PageBackgroundPrimary}" Offset = "1"/>
<GradientStop Color = "{Binding ColorsBo.PageBackgroundGradient}" Offset = "0"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Grid.Background>
.... more xaml to fill the page
</Grid>
Я не согласен. Если кто-то борется, как я, как переключать кисть градиента с кистью изображения, они получат фантастический ответ Майкла, потому что вы отметили его как дубликат.
Вы можете просто назначить экземпляры любого производного от Brush класса свойству элемента Background. Это тривиально, и требовать не является моделью представления. Хотя привязка свойства Background - это нормально, в этом нет строгой необходимости. Когда вы спрашиваете, как программно переключать Background между ImageBrush и LinearGradientBrush, простой ответ - установить свойство для экземпляра каждого из них.
Дубликаты связаны и их можно увидеть на боковой панели. Люди, испытывающие трудности, будут часто посещать повторяющиеся ссылки, чтобы прочитать другие ответы. Ничего не потеряно, если пометить пост как дубликат.
Вы в основном сами ответили на вопрос в своем коде.
Grid.Background
- это DependencyProperty
из Type
Brush
. Это означает, что мы можем преобразовать любой bind
в Brush
.
Как вы решите сделать эту привязку, зависит от вас, и из нее можно получить множество интересных стилей / функций.
Вот очень простая модель ViewModel, которая как бы демонстрирует это.
using System.ComponentModel;
using System.Windows.Media;
namespace Question_Answer_WPF_App
{
public class BackgroundViewModel : INotifyPropertyChanged
{
private readonly SolidColorBrush DefaultBrush = new SolidColorBrush(Colors.BlueViolet);
private Brush background;
public event PropertyChangedEventHandler PropertyChanged;
public BackgroundViewModel() => background = DefaultBrush;
public Brush Background
{
get => background;
set
{
background = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Background)));
}
}
}
}
Тогда вы можете использовать это так ...
<Grid Name = "myGrid"
Background = "{Binding Background}">
...
Просто чтобы помочь тебе, я сделал тебе немного лучше. Вот несколько предустановленных кистей в ViewModel и Grid в View. Вы можете скопировать и вставить все это как есть, без кода, и это будет работать. (Обратите внимание, что я специально использовал 3 разные кисти: SolidColorBrush, ImageBrush и LinearGradientBrush. Их больше, и можно использовать любую.)
ViewModel
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace Question_Answer_WPF_App.ViewModels
{
public class BackgroundViewModel : INotifyPropertyChanged
{
private Brush selectedBackground;
public BackgroundViewModel()
{
var brushes = new List<Brush>
{
new SolidColorBrush(Colors.BlueViolet),
new ImageBrush(new BitmapImage(new Uri("http://i.stack.imgur.com/jGlzr.png", UriKind.Absolute))),
new LinearGradientBrush(Colors.Black, Colors.White, 45)
};
BackgroundOptions = brushes;
SelectedBackground = BackgroundOptions.FirstOrDefault();
}
public event PropertyChangedEventHandler PropertyChanged;
public IEnumerable<Brush> BackgroundOptions { get; }
public Brush SelectedBackground
{
get => selectedBackground;
set
{
selectedBackground = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedBackground)));
}
}
}
}
Вид
<Window x:Class = "Question_Answer_WPF_App.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ViewModels = "clr-namespace:Question_Answer_WPF_App.ViewModels"
mc:Ignorable = "d"
Title = "MainWindow"
Height = "500"
Width = "800">
<Window.DataContext>
<ViewModels:BackgroundViewModel />
</Window.DataContext>
<Grid Background = "{Binding SelectedBackground}">
<ComboBox ItemsSource = "{Binding BackgroundOptions}"
SelectedItem = "{Binding SelectedBackground}"
Width = "250"
Height = "40"
VerticalAlignment = "Top"
HorizontalAlignment = "Left"
Margin = "12">
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid Background = "{Binding}"
Height = "40"
Width = "200" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
</Window>
Снимки экрана
Святая хрень !!! Отличный ответ !!! Это именно то, что я ищу! Спасибо!!!
myGrid.Background = new ImageBrush(...)
илиmyGrid.Background = new LinearGradientBrush(...)