У меня создаются кнопки в окне cs приложения WPF. Я хочу взять одну из кнопок и заполнить ее одной буквой, но чтобы в правом верхнем еще был маленький значок *3. Для этого заполняю кнопку grid и в этот grid помещаю 2 текстблока соответственно с строками столбцами
Grid _gridforbutton = new Grid();
TextBlock _double = new TextBlock();
_double.Text = "*3";
_double.Foreground = Brushes.Red;
_double.FontSize = 5;
TextBlock _word = new TextBlock();
_word.Text = letter;
_word.TextAlignment = TextAlignment.Center;
_word.FontSize = 30;
_gridforbutton.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(5) });
_gridforbutton.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(25) });
_gridforbutton.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(5) });
_gridforbutton.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(25) });
_gridforbutton.Children.Add(_double);
Grid.SetRow(_double, 0);
Grid.SetColumn(_double, 1);
_gridforbutton.Children.Add(_word);
Grid.SetRowSpan(_word, 2);
Grid.SetColumnSpan(_word, 2);
btn1.Content = _gridforbutton;
Проблема в том, что я хочу сделать так, будто буква заполняет всю кнопку, а значок *3 в правом крайнем углу как будто добавлен. Но в итоге *3 располагается сверху а кнопку почему-то не видно полностью
И так, посмотрим на вашу задачу, что требуется? А требуется нам некая кнопка, которая будет иметь дополнительные значения, иметь свой стиль и все это должно быть удобно! Для таких целей можно использовать UserControl. Давайте сделаем подобный:
В .cs файл нам надо задать DependencyProperty на все доп свойства нашего контрола, пишем и получаем что то вроде этого:
public partial class CustomButton : UserControl
{
public CustomButton()
{
InitializeComponent();
}
public Visibility DoubleVisibility
{
get => (Visibility)GetValue(DoubleVisibilityProperty);
set => SetValue(DoubleVisibilityProperty, value);
}
public Brush DoubleBackground
{
get => (Brush)GetValue(DoubleBackgroundProperty);
set => SetValue(DoubleBackgroundProperty, value);
}
public Brush DoubleForeground
{
get => (Brush)GetValue(DoubleForegroundProperty);
set => SetValue(DoubleForegroundProperty, value);
}
public string DoubleText
{
get => (string)GetValue(DoubleTextProperty);
set => SetValue(DoubleTextProperty, value);
}
public string Text
{
get => (string)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
public ICommand ButtonCommand
{
get => (ICommand)GetValue(ButtonCommandProperty);
set => SetValue(ButtonCommandProperty, value);
}
public static readonly DependencyProperty DoubleVisibilityProperty =
DependencyProperty.Register("DoubleVisibility", typeof(Visibility), typeof(CustomButton), new PropertyMetadata(Visibility.Visible));
public static readonly DependencyProperty DoubleBackgroundProperty =
DependencyProperty.Register("DoubleBackground", typeof(Brush), typeof(CustomButton), new PropertyMetadata(new SolidColorBrush(Color.FromArgb(255, 252, 74, 38))));
public static readonly DependencyProperty DoubleForegroundProperty =
DependencyProperty.Register("DoubleForeground", typeof(Brush), typeof(CustomButton), new PropertyMetadata(Brushes.White));
public static readonly DependencyProperty DoubleTextProperty =
DependencyProperty.Register("DoubleText", typeof(string), typeof(CustomButton), new PropertyMetadata("0"));
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(CustomButton), new PropertyMetadata("Text"));
public static readonly DependencyProperty ButtonCommandProperty =
DependencyProperty.Register("ButtonCommand", typeof(ICommand), typeof(CustomButton), new PropertyMetadata(null));
}
Отлично! Теперь нужно сделать вид нашего контрола. Так, как нам требуется кнопка, то давайте перепишем ей дизайн:
<Button Command="{Binding ButtonCommand, ElementName=Control}" CommandParameter="{Binding}">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Grid.Effect>
<DropShadowEffect BlurRadius="4" ShadowDepth="0" Direction="-90" Opacity="0.5"/>
</Grid.Effect>
<Border Name="Mask" Background="White" CornerRadius="7" Margin="5"/>
<Border Background="White" Margin="5">
<Border.OpacityMask>
<VisualBrush Visual="{Binding ElementName=Mask}"/>
</Border.OpacityMask>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Grid Visibility="{Binding DoubleVisibility, ElementName=Control, FallbackValue=Visible, TargetNullValue=Visible}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<Grid>
<Polygon Points="100,0, 0,100 0,0"
Fill="{Binding DoubleBackground, ElementName=Control, FallbackValue=#FC4A26, TargetNullValue=#FC4A26}"
Stretch="Uniform"
HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Viewbox HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBlock Padding="5,5,25,0"
Text="{Binding DoubleText, ElementName=Control, StringFormat=x{0}, FallbackValue=x0, TargetNullValue=x0}"
Foreground="{Binding DoubleForeground, ElementName=Control, FallbackValue=White, TargetNullValue=White}"/>
</Viewbox>
</Grid>
</Grid>
<Viewbox Grid.ColumnSpan="2" Grid.Column="0">
<TextBlock Margin="10" Foreground="#4d4d4d"
Text="{Binding Text, ElementName=Control, FallbackValue=Text, TargetNullValue=Text}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Viewbox>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
Самому UserControl задаем свойством его имя:
Name="Control"
Ну что, это уже как минимум втрое облегчит вашу задачу (а может даже и решит ее), ведь у вас уже готовый контрол и вместо редактирования кнопки через код, вы можете сразу вызвать этот самый контрол, задав ему все необходимые значения.
Но! Я не устану повторять, что создавать объекты через код не верный подход! WPF это не WinForms, тут есть очень замечательная вещь - Binding. А отличным помощником для этих всех привязок является MVVM паттерн, а у него есть очень забавное правило - "Код не должен знать о View (xaml разметке)".
Давайте я покажу простейшую реализацию MVVM, где мы будет выводить несколько созданных нами кнопок:
Нам потребуется пару классов для команд:
public class RelayCommand<T> : ICommand
{
private Action<T> action;
public RelayCommand(Action<T> action) => this.action = action;
public bool CanExecute(object parameter) => true;
#pragma warning disable CS0067
public event EventHandler CanExecuteChanged;
#pragma warning restore CS0067
public void Execute(object parameter) => action((T)parameter);
}
public class RelayCommand : ICommand
{
private Action action;
public RelayCommand(Action action) => this.action = action;
public bool CanExecute(object parameter) => true;
#pragma warning disable CS0067
public event EventHandler CanExecuteChanged;
#pragma warning restore CS0067
public void Execute(object parameter) => action();
}
Далее нам нужен класс, который будет описывать свойства нашей кнопки:
public class ButtonViewModel
{
public Visibility DoubleVisibility { get; set; }
public Brush DoubleBackground { get; set; }
public Brush DoubleForeground { get; set; }
public string DoubleText { get; set; }
public string Text { get; set; }
public ICommand Command { get; set; }
}
Теперь нам нужно сделать основной класс, который будет задан как DataContext, некий MainViewModel. В нем создадим коллекцию, заполним ее и сделаем обработчик наших кнопок:
public class MainViewModel
{
public ObservableCollection<ButtonViewModel> Buttons { get; set; } = new ObservableCollection<ButtonViewModel>();
public MainViewModel()
{
Buttons.Add(new ButtonViewModel
{
Text = "A",
DoubleText = "2",
DoubleVisibility = Visibility.Visible,
DoubleBackground = Brushes.Green,
Command = new RelayCommand<ButtonViewModel>(Clicked)
});
Buttons.Add(new ButtonViewModel
{
Text = "B",
DoubleText = "10",
DoubleVisibility = Visibility.Visible,
Command = new RelayCommand<ButtonViewModel>(Clicked)
});
Buttons.Add(new ButtonViewModel
{
Text = "C",
DoubleVisibility = Visibility.Collapsed,
Command = new RelayCommand<ButtonViewModel>(Clicked)
});
}
void Clicked(ButtonViewModel obj)
{
Console.WriteLine($"Кнопка {obj.Text} нажата!");
}
}
Привяжем все это дело:
private MainViewModel MainViewModel { get; } = new MainViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = MainViewModel;
}
Ну и последнее, создаем View для этого всего. Для этого классно подходит ItemsControl:
<ItemsControl ItemsSource="{Binding Buttons}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:CustomButton Width="150" Height="150"
ButtonCommand="{Binding Command}"
Text="{Binding Text}"
DoubleVisibility="{Binding DoubleVisibility}"
DoubleBackground="{Binding DoubleBackground}"
DoubleForeground="{Binding DoubleForeground}"
DoubleText="{Binding DoubleText}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Фух, ну все, время запускать и любоваться результатом:
Ну, на этом все, надеюсь я показал вам правильную работу с элементами в WPF. Удачного изучения!
Пытаюсь подключить CEFПри компиляции возникает вышеуказанная ошибка
Например: На c++ программа циклически считывает данные ожидая определенного событияКак только это событие произойдет должно высветиться...
У меня есть списокВ нем элементы вида: "_something":"",
Паттерн producer/consumer достаточно часто встречается в многопоточном программированииЕго смысл состоит в том, что один или несколько потоков...