So, let's see what you need. And we need a button that will have added value, a style, and all that should be convenient! UserControl can be used for such purposes. Let's do this:We're on our project by the right button of mouse - add - User of control - we're thinking about Ok's name and strap.Next, we'll have almost everything the same as the usual window.In the .cs file, we need to ask DependencyProperty for all the properties of our counter, write and get something like this: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));
}
Great! Now we have to pretend to be our controller. Now, as we need a button, let's rewrite her design:<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's own name:Name="Control"
Well, at least three times that'll make it easier for you (and maybe even solve it), because you've already had a ready control and instead of editing the button through the code, you can immediately call this control by giving it all the necessary meanings.But! I can't tell you that building objects through the code isn't the right approach! WPF is not WinForms, there's a very great thing - Binding. And the great assistant for all these connections is MVM patternne, and he has a very funny rule, "Code shouldn't know about View.Let me show you the simplicity of the MVM, where we will take out some of our buttons:We're gonna need a couple of classes for the team: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();
}
Next, we need a class that will describe the properties of our button: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; }
}
Now we need to do the basic class that will be assigned as DataContext, some MainViewModel. We'll build a collection, fill it up and make a processor of our button: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} нажата!");
}
}
Let's get this case together:private MainViewModel MainViewModel { get; } = new MainViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = MainViewModel;
}
Last thing we do is create a View for this. It's a classic 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>
Ew, all the time to start and love the result: Well, that's all I hope I showed you the right work with the elements at WPF. Good study!