M
M
Maxim Siomin2020-11-11 19:26:48
css
Maxim Siomin, 2020-11-11 19:26:48

How to create such an element in wpf?

I want a button that looks like plain text and changes its color to the one I want when I hover over it with the mouse. And it should look like a textblock, not a button

Answer the question

In order to leave comments, you need to log in

2 answer(s)
N
Nikolay Talanov, 2016-07-26
@HHabar

A bunch of svg, the animation of which is tied to the current "progress" (page scroll). For example, this can be stirred up using GSAP Timeline, create a timeline, stuff a carload of all possible animations, correctly placed at certain stages, and then change the progress of the timeline in relation to the ratio of the scroll position to the total scroll height.
I can say with confidence that the creation of this site took a lot of tears from developers and designers.

I
Igor Tkhorik, 2020-11-12
@MaxSiominDev

Here is a small manual that is described very concisely and you need to read it while looking at the project itself. Link to it.
In order to make your customcontrol you need two things:
1. View representation of the element itself.
2. The class that will be the data context for this View representation.
Our application will be based on the MVVM pattern, if you are unfamiliar with this, read here . It is also necessary to understand what binding is in WPF, if we don’t know, read here and here . In short, binding is such a thing.
which allows you to update the state of the UI element when its properties change in the data context, if this is not done, then you will need to update the state in the UI through the Dispacher, and this will freeze
our UI and do not do this. Therefore, we will add the Services Folder to our project and add the ObservableObject and RelayCommand classes there (the code of all [classes is in the repository). ObservableObject will describe the property binding mechanism and we will simply inherit from this class by calling the OnPropertyChanged method in the property's set parameter.
We will divide the binding of our properties into two stages, first we will make data update events in the button model itself and then we will indicate which data context to bind to and which properties to bind to in XAML (our button itself).
First, let's describe the button interface with the IButtonStyle type and create an abstract AButton class that inherits ObservableObject,IButtonStyle. In the AButton class, add fields reflecting properties in IButtonStyle.

private string _content;
        public string content
        {
            get => _content;
            set { OnPropertyChanged(ref _content, value); }
        }

Here, a property inherited from the IButtonStyle (content) interface is implemented, which returns. the _content field and set the value using the OnPropertyChanged(ref _content, value) method, and do the same with all the other properties that we inherit. We will then bind these properties to the properties of our UserControl in the XAML.
<Label Content="{Binding content}" Foreground="{Binding fontColor}" FontSize="{Binding fontSize}"/>

Now we need to make it so that when you hover over our element, it changes color. To do this, we need to create dependency properties of type RelayCommand for our button.
private RelayCommand _mouseEnterCommand;
        /// <summary>
        /// Команда входа мышки в поле контролера
        /// </summary>
        public RelayCommand MouseEnterCommand
        {
            get { return _mouseEnterCommand; }
            set
            {
                OnPropertyChanged(ref _mouseEnterCommand, value);
            }
        }

        private RelayCommand _mouseLeaveCommand;
        /// <summary>
        /// Команда покидания мышки поля контролера
        /// </summary>
        public RelayCommand MouseLeaveCommand
        {
            get { return _mouseLeaveCommand; }
        }

        private RelayCommand _mouseDownCommand;
        /// <summary>
        /// Команда щелчка мышки
        /// </summary>
        public RelayCommand MouseDownCommand
        {
            get { return _mouseDownCommand; }
        }

And we will make a couple of events and methods for directly setting values ​​​​(color or font size)
event Action _mouseEnter;
        event Action _mouseLeave;

        void MouseEnterEventMethod()
        {
            fontColor = fontColorMouseEnter;
        }
         void MouseLeaveEventMethod()
        {
            fontColor = fontColorNormal;
        }

        private void MouseEnter()
        {
            this._mouseEnter.Invoke();
        }

        private void MouseLeave()
        {
            this._mouseLeave.Invoke();
        }

        public void MouseEnter(object param)
        {
            MouseEnter();
        }

        public void MouseLeave(object param)
        {
            MouseLeave();
        }

And subscribe to it in the class constructor
public AButton(string _content)
        {
            content = _content;
            _mouseEnter += this.MouseEnterEventMethod;
            _mouseLeave += this.MouseLeaveEventMethod;

            this._mouseEnterCommand = new RelayCommand(MouseEnter);
            this._mouseLeaveCommand = new RelayCommand(MouseLeave);
        }

And so we now have the content, fontColor, fontColorNormal, fontColorMouseEnter properties and the MouseEnterCommand, MouseLeaveCommand, MouseDownCommand commands ready to be bound.
Well, let's make a couple of classes of our buttons
class ButtonStyleA : AButton
    {
       public ButtonStyleA(string _content) : base()
        {
            content = _content;
            base.fontColor = "#FF5733";
            base.fontColorNormal = "#FF5733";
            base.fontColorMouseEnter = "#61FF33";
            fontSize = 16;
        }
    }

class ButtonStyleB : AButton
    {
        public ButtonStyleB(string _content) : base()
        {
            content = _content;
            fontColor = "#33B5FF";
            fontColorNormal = "#33B5FF";
            fontColorMouseEnter = "#E933FF";
            fontSize = 12;
        }
    }

Now we need to create a data context for our element, so in the ViewModels folder Let's create a class
public class MenuButtonViewModel
    {
        public AButton MenuButton { get; set; }

        public MenuButtonViewModel(AButton menuButton)
        {
            MenuButton = menuButton;
        }
    }

Very often, all bindings and Commands are implemented in the data context class (MenuButtonViewModel).
Let's create our UserControl in the Views folder, call it MyButton and add a reference to the MouseBehaviour class. Now let's bind the MouseMoveCommand, MouseLeaveCommand, MouseDownCommand events to our properties of the RelayCommand type.
xmlns:u="clr-namespace:WpfMvvmDemo.Services"
<Grid u:MouseBehaviour.MouseMoveCommand="{Binding MenuButton.MouseEnterCommand}" u:MouseBehaviour.MouseLeaveCommand="{Binding MenuButton.MouseLeaveCommand}" u:MouseBehaviour.MouseDownCommand="{Binding MenuButton.MouseDownCommand}">

And also bind the Label properties to the AButton properties
<Label Content="{Binding MenuButton.content}" Foreground="{Binding MenuButton.fontColor}" FontSize="{Binding MenuButton.fontSize}"/>

Now we need a data context for the main window of our application. Let's call it RootViewModel and create in it two buttons of different types, ButtonStyleA and ButtonStyleB.
public class RootViewModel : ObservableObject
    {
        public MenuButtonViewModel MainPageButton { get; set; }
        public MenuButtonViewModel SecondPageButton { get; set; }

        public RootViewModel()
        {
            MainPageButton = new MenuButtonViewModel(new ButtonStyleA("Главная"));
            SecondPageButton = new MenuButtonViewModel(new ButtonStyleB("Вторая"));
        }

        private void ChangeToMainPage()
        {

        }


        private void ChangeToSecondPage()
        {

        }
    }

In the MainWindow Class, create an instance of the RootViewModel type and make it the data context for the MainWindow
private RootViewModel RootVM;
        public MainWindow()
        {
            InitializeComponent();
            RootVM = new RootViewModel();
            this.DataContext = RootVM;
        }

In the XAML representation of our main window MainWindow, we will add a link to our CustomController and now we will rebuild the project, otherwise the ide may not see our buttons, and then we will add the buttons themselves and set the data context for them (these are the properties of the MenuButtonViewModel type that we created in the RootViewModel)xmlns:bn="clr-namespace:WpfMvvmDemo.Views"
<Grid >
        <StackPanel Orientation="Vertical">
            <bn:MyButton DataContext="{Binding MainPageButton}" />
            <bn:MyButton DataContext="{Binding SecondPageButton}"/>
        </StackPanel>
    </Grid>

Well, that's all, you can run and enjoy. For g0vnokod please do not scold.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question