Source link: https://github.com/vickyqu115/riotslider tutorial video (https://www.bilibili.com/video/BV1uy421a7yM)
This article is a technical review of the WPF RiotSlider tutorial videos, and you can search our account to watch the full video tutorial content.
League of Legends style slider with WPF |
Detailed mechanics for analyzing and customizing WPF Slider controls
In WPF, basic controls like Button and ToggleButton have a simple structure and logic and can be implemented entirely in XAML without the need for background code. In contrast, more complex controls such as TextBox, ComboBox, and Slider require complex C# code with XAML to do what it does.
Understanding and applying the complex configuration of WPF controls allows for more elegant and flexible design and development of custom controls. By mastering these basic components, we can solve some of the problems in the MVVM development model and build higher-quality WPF applications.
This exploration of the WPF Slider widget is all about gaining a deeper understanding of how it's built and its inner workings. Despite the sheer volume of code, it's nearly impossible to get inside every WPF control, but there's no need to worry too much.
All of WPF's source code is open source and managed on GitHub. This means that we can always find and analyze specific controls as needed.
In addition to the Slider controls, we plan to dissect and analyze more complex and diverse controls in the future. So if you're interested in this part of the story, don't forget to follow our Bilibili or Youtube channels, and we'll share the source code on GitHub.
League of Legends style slider with WPF |
Content catalog
WPF series of tutorials
specification
Create an app project
Analyze the main features of Slider
Extract the original style process
Extract the source code for analysis
Inspect the backend code (GitHub open source)
Cross-platform OnApplyTemplate
To summarize the Slider analysis
Create a Riot-style Slider (custom controls)
Project creation and start preparation
TextBlock(Hi Slider)
Add references and test executions
Set the size of the Riot Slider
PART_Track
Add a slider
Adjust the gap between the slider and the track
PART_SelectionRange
Add Riot-inspired design elements
Implement a Riot-style slider
Declare a slider resource
Completing the RiotSlider Template (Finishing touches)
Final Comments
WPF series of tutorials
So far, we've published four tutorial series on YouTube and BiliBili. English and Chinese dubbing is also available, with Korean subtitles. We hope that these videos, combined with detailed source code and detailed explanations, will improve your understanding of WPF.
[x] 主题切换:BiliBili,GitHub
[x] Riot ??:BiliBili,GitHub
[x] 魔法导航栏:BiliBili,GitHub
[x] Riot ??:BiliBili,GitHub
specification
The project is based on .NET Core, but is limited to the Windows platform due to the use of WPF. The project can be run with VS2022 with .NET 8.0 or on JetBrains' Rider.
[x] 操作系统:Microsoft Windows 11
[x] IDE:Microsoft Visual Studio 2022
[x] 版本:C# / .NET 8.0 / WPF / 仅限 Windows
[x] NuGet:Jamesnet.Wpf
It is recommended to use the latest version of Windows as the operating system. Of course, if you consider extending the platform to Avalonia UI, Uno Platform, MAUI, etc., you can also use MacOS as a secondary device. We also use both Thinkpad and MacBooks in our programming environment. It's important to note that Visual Studio isn't available on MacOS or Linux-based systems, so Rider is the only alternative. vscode
3. Create an app project
First, we need to create a WPF Application project.
[x] 项目类型:WPF Application
[x] Project Name: DemoApp
[x] Project version: .NET 8.0
4. Analysis of the main functions of Slider
Unlike simple controls like Buttons, WPF Slider controls have a very large number of properties. In particular, these properties play an important role in the functionality of the control, so it is worth taking a closer look. Some of these special main attributes are as follows:
Orientation:
The controls provided by WPF are generally generic in nature. Slider controls are no exception, with the Orientation property being an example. With this property, you can specify a horizontal or vertical orientation.
Here we can see that the trigger switches (ControlTemplate) templates based on the Orientation property. Therefore, by looking at the detailed structure of this control, it is easy to understand the importance of the Orientation property.
That's an interesting part. Can you imagine or apply the concept of switching templates via Orientation before seeing the original code? Open source projects can really inspire developers in this way. Also, with this code, we can confirm that the best time to switch templates is in "Style.Trigger".
In this tutorial video, we'll only implement the Horizontal orientation, so we won't be branching via Orientation. However, it is also recommended that you try to implement the Vertical direction and submit a Pull Request to us through a fork, which is a small task.
So let's take a look at the effects of applying the Horizontal and Vertical properties respectively:
[x] Orientation: Horizontal
League of Legends style slider with WPF |
This can also be seen in the SelectionRange (blue) area to be discussed below.
These properties represent the minimum/maximum value and the current value, respectively, and they are both properties of type double. Internally, the size and scale of the control are automatically calculated based on these values, as well as the position of the Range and Value values.
Since these properties are all DependencyProperties, they can be dynamically interacted with through bindings. For example, in an MVVM structure, you can use these three values to dynamically change the scope based on a specific scenario or to implement a variety of interesting applications.
These two properties (SelectionStart/SelectionEnd) are used to set a specific area. Actually, this area doesn't contain any special features, just to specify a compartment and highlight it visually. IsSelectionRangeEnabled is a property used to indicate whether the region is enabled or not, and depending on whether it is enabled, the value of the Visibility property (Visible/Collapsed) of the region is toggled by a trigger.
To sum up, these features are only for simple area display, so it can be confusing whether or not they are needed. But since they are common in different designs and fields, the need for it can be understood and foreseen. Respect the style preferences of 20 years ago
In fact, when these are applied in combination with Value values, they can have very interesting effects, as shown below:
Surprisingly, the Value value is bound via SelectionEnd, and the Selection (Range) range changes dynamically each time the value changes. I wonder if the WPF development team did it on purpose? All in all is great, and the implementation is very simple.
This part plays a very important role in the Riot-style Slider (CustomControl) that will be implemented later, so please pay attention.
5. The process of extracting the original style
As shown above, WPF is managed in an open-source manner through GitHub repositories, so we can see the source code for all controls. But since the repository contains the solution and all the projects and files, it is very difficult to extract only the contents of a specific control section.
Luckily, Visual Studio provides the ability to extract the default style (Template) for a specific control and render it as a GUI. Therefore, we can easily extract the corresponding code without having to look for it step by step in the open source code.
Similar to Identity Scaffolding in Blazor (although slightly different in nature, it can be compared to this for the sake of understanding).
On top of that, when the original styles are extracted through Visual Studio, they are actually connected as modifiable assets, so you can customize the design and functionality right away. Therefore, not only Slider, but also the original styles and templates of all controls can be extracted, which has a high application value in the process of WPF's research and learning.
This extraction is not necessarily available in commercial components such as Infragistics, Syncfusion, ArticPro, etc. Each company has a different scope and policy of disclosure, and in most cases, it is more likely to modularize and lead customization through DataTemplates rather than ControlTemplates. So, if you're interested, you can also look into the way of using the components.
However, the extraction step can only be done in the design area of the UserControl interface in the Partial form, where you can select the control and right-click on it. In this process, you need to select the Specify Style Name/Specify Copy Location for Extracted Styles option.
Can you try to look it up in VScode or Rider as well to see if there is a similar feature available?
In general, specifying a name is the right choice for testing or administration. If you select the "Apply to all" item without specifying a name, the resulting style will be applied globally based on the defined extraction location. So you need to fully understand this and extract it carefully.
In the video, you set the name and specify the definition location as Application. As a result, the extracted resources (if the file exists) will be included in the Resources area of the App.xaml file.
Personally, it is recommended that when doing this extraction, it should be carried out in a new project as much as possible in a test nature. Actually doing this in a live project can lead to some minor bugs and problems, so it's a good option from the standpoint of avoiding side effects.
6. Extracted source code analysis
As shown in the tutorial video, we have successfully extracted the style of the Slider control. Let's take a look at the resources in the App.xaml file and examine the important considerations one by one.
确认 Orientation 分支:
In explaining the Orientation property earlier, we briefly mentioned the triggers and switching mechanism, but now let's actually take a look at the source code of the implementation.
The following styles are extracted WPF base style originals that contain the SliderStyle1 template. (The actual application is error-free and works properly.) )
In this way, the structure of the style can be seen at a glance by modularly managing the ControlTemplate template. Even in situations where switching isn't required, it's a management style worth trying. We use this approach a lot, and we get inspiration from the process.
As a result, the actual functionality of the Slider control is implemented in the SliderHorizontal and SliderVertical ControlTemplate templates, respectively.
Now let's take a look at the default SliderHorizontal(ControlTemplate) template.
确认ControlTemplate:
Check out the Horizontal/Vertical dedicated templates separately. It can be found in the App.xaml file.
As shown above, the source code for Horizontal/Vertical is implemented separately. The implementation of both is the same, differing only in the direction of the design.
Name:
PART_
In the structure of a custom control, it is important to keep the XAML and the code backend tightly connected. However, in order for this connection to take place, it is necessary to pass through
GetTemplateChild
method to find the control name, which is not ideal in terms of readability. In order to improve this development method and systematically manage it, it is used
PART_
Naming conventions.
It's a naming convention, and it's passed at all
GetTemplateChild
Find the name of the control with the prefix in front of it
PART_
prefix to speculate on its functionality in XAML. Therefore, when analyzing a control template, if you find a control template
PART_
The names of the controls at the beginning, you can guess that they are required elements, and anticipate in advance the possible side effects of removing them.
Ultimately, this is very helpful for implementing custom controls. In addition, this rule is not only applicable in WPF, but is also common in other cross-platform frameworks that share XAML, and is an important and important part that cannot be ignored.
Slider
controls
PART_
control
PART_Track
PART_SelectionRange
The results showed that in addition to these two
PART_
Outside of controls, no other controls are used in the code backend. This is guaranteed by this naming convention. Therefore, it is very important to strictly follow this rule in the development of custom controls.
Before the change, you can see the range area that is displayed normally.
After the change:
PART_SelectionRange1
League of Legends style slider with WPF |
After the change, the range area is no longer displayed.
Again, due to the inability to find it inside
PART_SelectionRange
control, the target of the range area cannot be calculated.
It can be seen that WPF controls, although relatively loosely constructed, have a modular structure. Therefore, if we can take advantage of these features, we can not only make good use of the features that have already been implemented, but also eliminate a lot of unnecessary features.
7. Code behind 确认 (GitHub 开源代码)
We discussed this in detail earlier
PART_
Naming conventions for controls and their impact, it's time to look at how these controls are used in actual classes.
The Code behind region cannot be confirmed by direct extraction. Therefore, we need to look through the official source code in the WPF codebase. In this section, we recommend checking out our video tutorial to learn how to view it.
It's important to note here that the type of the Track is the same as in XAML, but the SelectionRange is defined as a FrameworkElement, not the original Rectangle, which means that the SelectionRange can be any type of control, not just a Rectangle. This is a deliberate attempt to make the type definition more flexible.
Therefore, we can speculate that the SelectionRangeElement (defined as the FrameworkElement type) only handles the basic functionality that this type can handle.
Since the logic of Orientation (horizontal/vertical) is practically the same, we only need to focus on the logic of the horizontal direction.
It is through this (UpdateSelectionRangeElementPositionAndSize) method that determines the size and position of the SelectionRange. Although the amount of source code may seem like a lot, it's easy to see that the handling of SelectionRange is relatively concise, given the duplication of the Orientation branching logic.
In this way, we can look up and analyze the CustomControl control by reversing it as well
PART_
How controls are handled internally.
8. OnApplyTemplate in Cross-Platform
Many cross-platform frameworks share many similarities to WPF in design, so they follow a similar pattern in their processes. So, we can take a look at implementations on other platforms based on the OnApplyTemplate we analyzed earlier.
List of platforms to share OnApplyTemplate designs:
[x] AvaloniaUI
[x] Uno Platform
[x] OpenSilver
[x] MAUI
[x] Xamarin
[ ] UWP
[ ] WinUI 3
[ ] Silverlight
Among these platforms, the original source code for AvaloniaUI, Uno Platform, OpenSilver, MAUI, and Xamarin, which has been checked, is worth looking at further.
It is worth mentioning that, with the exception of Silverlight, the codebases for these platforms are managed on GitHub by the official Microsoft organizations Dotnet or xamarin, so we can easily find them.
In WPF, we usually use Track when declaring variable names, while in MAUI we use the underscore prefix instead. So comparing the naming conventions and development patterns of various platforms is also a very interesting thing in open source.
OpenSilver: OnApplyTemplate
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
// 获取组件
...
ElementVerticalThumb = GetTemplateChild(ElementVerticalThumbName) as Thumb;
...
}
Seems to use a similar annotation style to Uno.
Xamarin: OnApplyTemplate
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
FormsContentControl = Template.FindName("PART_Multi_Content", this)
as FormsTransitioningContentControl;
}
Although slightly different, they all share a design similar to WPF.
9. Summarize the Slider analysis
We analyzed WPF's Slider control in detail. From this analysis, we can confirm that WPF's (CustomControl) control design is very sophisticated. These rules apply to other controls as well, and are a very important foundation when designing new controls.
Some people think that WPF is dead, but in fact WPF still exists and continues to evolve. Diving into WPF opens up endless possibilities and fun.
In the past, we may have dreamed of doing all of our development with WPF, but with the advent of platforms like Xamarin and .NET Core, that dream has become a reality. It's the result of the efforts of many developers who love WPF.
Through this analysis, we understand the importance of basic control analysis. It is recommended that you review and learn these contents again through the tutorial videos.
Next, we'll create a new Riot-style (CustomControl) Slider based on this analysis.
10. Create a Riot-style Slider (CustomControl) control
Now, based on the analysis of Slider, we will take advantage of the characteristics of the controls and implement it with a minimum of design. In this process, the core is to take advantage of the PART_ part and not use any code to complete the control.
motivation
It's not common to use the default Slider directly, so we need inspiration. As it happens, I tried to design a Slider based on Riot Games' League of Legends game, so I decided to use that as inspiration for the controls.
Actually, this design started a few years ago when I wanted to implement a high-level game client with WPF and started the development of the League of Legends application. So, if you want to see this Slider widget in action, check out this repository. Anyone can contribute through Fork, and there have been more than 80 forks recorded so far.
League of Legends style slider with WPF |
So let's start creating a new (CustomControl) Slider control.
11. Create and launch the project
Now that you've created your DemoApp (WPF application) project earlier, it's time to create a CustomControl library project. If you want to continue in the DemoApp project, you can skip the project creation process.
Project Creation:
[x] Project name: SliderControl
[x] 项目类型:WPF CustomControl Library
[x] Project version: .NET 8.0
League of Legends style slider with WPF |
To delete the underlying file:
[x] AssemblyInfo.cs
[x] Themes/Generic.xaml
[x] CustomControl1.cs
League of Legends style slider with WPF |
These deleted files are actually required to make up the CustomControl control, but we delete them in order to reorganize the project structure or location.
During the process of recreating the control, the deleted elements are automatically regenerated, so there is no need to worry about file deletion.
Create a (CustomControl) file:
[x] 创建RiotSlider.cs (CustomControl)Class
League of Legends style slider with WPF |
DefaultStyleKeyProperty related statements are included with the static constructor only if the file type is set to the CustomControl class. If you select the wrong type during the creation process, the CustomControl-related code will be missed and will need to be entered manually, so be sure to check each step carefully.
public class RiotSlider : Slider
{
static RiotSlider()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(RiotSlider), new FrameworkPropertyMetadata(typeof(RiotSlider)));
}
}
Confirm the auto-generated file:
[x] Properties/AssemblyInfo.cs
[x] Themes/Generic.xaml
League of Legends style slider with WPF |
If you don't set the file type to the CustomControl class, these files won't be automatically generated either. This is important to note.
12. TextBlock (Hi Slider)
Next is the step to test that the Slider control has been correctly configured to the CustomControl format.
When you first create a CustomControl Slider widget, an empty ControlTemplate template is generated by default. So, in order to visually confirm the controls, we usually add some design elements. We'll add a temporary TextBlock and text here.
This will allow us to view and test the RiotSlider controls we have created in the DemoApp app.
Check the running result:
[x] Riot Slider: "Hi Slider"
League of Legends style slider with WPF |
At this point, we've finished configuring the (CustomControl) RiotSlider widget and confirmed that it is working properly.
Since the CustomControl method is more complex than the UserControl method, you may encounter some difficulties before becoming familiar with the process. Therefore, these difficulties need to be overcome through repetitive exercises.
Now, this RiotSlider widget has been modularized in the form of a CustomControl for easy management. We can upload this control to a GitHub repository for management, or publish it to a NuGet package for distribution. CustomControl modularity in WPF has many advantages in terms of management, so this should be taken into account when designing a project.
Of course, this project has already been released through the NuGet Package Store. Interesting, right?
14. Set the size of the Riot Slider
Next, we'll set the size of the control.
WPF provides very powerful and responsive layouts. As a result, when you specify the size of a control, it is often designed to be responsive. However, for some special controls, such as Slider, which contains many design elements, it may be necessary to set a fixed height or width to achieve a natural design. Therefore, it is important to respond flexibly according to the characteristics of the control.
This time, we're going to design a (Thumb) widget with a height of 50. Therefore, we pre-specify the height of the RiotSlider. In addition, although the width will be responsive as the movement path of the track, we will temporarily limit it to 200 for development convenience.
To better estimate the size of the control, you can temporarily change the background color to make it easier to identify the control. It's a little trick.
Check the running result:
[x] Check the control size: width/height
[x] Check the control color: background color
League of Legends style slider with WPF |
After confirming that there are no problems with the running results, you can remove the background color.
15. PART_Track
Track is the core control element of the Slider that includes the Thumb. Through the analysis, we can see the pass
PART_Track
Declared, the Slider control can handle all of these features. Therefore, it is very important to include this key element correctly in the implementation process.
Track is one of the few controls that inherits directly from the FrameworkElement instead of Control. This means that it doesn't qualify for designing layouts directly like ControlTemplate does. As such, it contains Thumb and builds the layout directly, so it can be assumed that this control is primarily focused on Thumb.
Define Thumb:
Next, we define the Thumb that moves on the Track.
This is an example of extending directly in Track and implementing Thumb. The grammar may be a little difficult to understand, but there are detailed visual explanations in the tutorial videos, and it is recommended that you watch the instructional videos.
In this Thumb example, defining a control via a template is different from a Track. This means that the Thumb inherits from the Control instead of the FrameworkElement, so the controls can be designed flexibly via the ControlTemplate.
Check the running result:
[x] 检查Thumb (Ellipse) 设计
[x] Check the Track movement function
League of Legends style slider with WPF |
Since the Thumb is designed to be an Ellipse shape, this large (50x50) ellipse moves within the Track area. However, if you change the name of the Track from
PART_Track
Change to a different name and the Thumb will not be able to move.
To reaffirm this relevance, you can try changing the name.
16. Add a slider bar
Next, let's add a slider. This step is just to add design elements and doesn't involve functionality. So omitting this step will not affect the functionality. However, since the next step is the SelectionRange phase and needs to incorporate design elements, this step also needs to be done carefully.
To modify the layout:
So far, there were only Track elements inside Border, but now you need to add a slider bar, so you'll need to modify the existing layout. Also, because Tracks and slider bars require an overlay effect, using Grid is the only option. So, start by wrapping the Track in the Grid.
Because you only need a simple overlay effect, you don't need to use Grid's RowDefinitions or ColumnDefinitions.
To add a slider bar that overlays with a Track:
The slider bar needs to be stacked with the Track, but it needs to be logically determined which element is in front (frontend) first. Because the Track's Thumb control needs to cover the slider bar area, you need to add the slider bar before you declare the track.
In addition, because you need to visually represent the length of the track, it is effective to use a layout like Border. In particular, Border's CornerRadius property can handle the effect of rounded corners, which can express richer designs than other controls.
Confirmation of operation results:
[x] 确认 Thumb 的移动: (Ellipse)
[x] 确认滑块条设计: (Border)
League of Legends style slider with WPF |
As you can see, the design and position of the slider bar should be in harmony with the movement path of the Track and the movement of the Thumb, which is the key point in this phase.
17. Adjust the error between the slider bar and the track
While the design and placement of the slider bar looks good, the track's range of movement actually limits the radius of the Thumb at the start and end. Looking at WPF's source code, we can see the following code:
The above code is for the case of Orientation="Horizontal". Therefore, if the value changes to vertical, you need to change it to Height.
From this code, we can deduce that the actual range of movement of the Track is also internally limited by the radius of the ThumbSize. As a result, the slider bar we added earlier is not managed internally by the Slider control
PART_
element, so you need to apply this rule manually. While this can be handled dynamically, in this step we use the Margin property to precisely adjust the error between the slider bar and the track movement range.
设置 Thumb Ellipse 的透明度:
To make it easier to work, specify the transparency of the Ellipse control.
In WPF, an object's transparency property, Opacity, is typically used when setting element transparency, but by using a color's alpha value, you can apply transparency to only a specific color. Here's a little trick from WPF that is well worth taking advantage of.
Apply the Margin of the slider bar to account for the radius of the Thumb:
The current width of the Ellipse is 50, so a margin of 25 is applied to the left and right.
As you can see, the maximum range of movement of the track and the design dimensions of the slider bar are exactly the same.
Of course, you can also consider the dynamic processing of this Sync operation later. One approach that comes to mind so far is to specify this slider bar control as
PART_
and then process it in CodeBehind. Of course, there are various other ways to do this, and it's worth thinking about.
18. PART_SelectionRange
The SelectionRange is an element that is responsible for specifying a specific Range range through the previous Slider analysis.
This control is the same as Track
PART_
element, the Slider control handles all of its functions internally, so it just needs to be placed correctly according to the agreed name. Since it is designed to be the same height as the slider bar, the height should be the same as the slider bar added earlier.
By synchronizing the value of SelectionEnd with the value of Value, you can dynamically express the Range range. Actually, the Slider control of the League of Legends client app is implemented in the same way.
Full code:
Combining the above steps, the complete code is as follows:
With that, we've done the addition of the SelectionRange and the synchronization of the slider bar with the Track.
处理 IsSelectionRangeEnabled 启用:
Considering the concept of Riot Slider controls, there may not be a need to deal with this feature. But since it can be easily achieved with triggers, we can try it out as we learn.
This section is not covered in the tutorial video.
We use the Geometry Path element to draw the Thumb icon instead of the image file, because it has the advantage of being able to change colors freely with color triggers and maintaining high vector-based quality.
This simple icon can be easily made by non-designers with Visual Studio Blend or tools like Figma or Illustrator. It's not difficult, it's worth a try.
When requesting vector icons from colleagues, it is recommended to use the SVG format and require the monochrome design of the icons to be a composition. In addition, there are plenty of open-source icons that are free to use. For example, Pictogrammers offers over 8000 monochrome design icons, including:
.SVG
、
.PNG
and
.XAML
Format. And with GitHub open source management, you can view major contributors or participate in open source projects.
x:Key rules for design resources such as colors often have uppercase or camel nomenclature, as well as namespace-like approaches. Personal advice is to be as brief as possible. While perceptions vary from year to year, there is a current tendency to keep things as brief as possible.
A closer look at the design style of League of Legends reveals a lot of use of gradients. The way to extract these colors is to use Photoshop or an app with an eyedropper color extraction feature.
For areas where gradients may be present, the eyedropper function can be used multiple times to extract the color. With a lot of practice, your eyes will also become sharper.
League of Legends style slider with WPF |
20. Implement a Riot-style Thumb
Now, we'll use the prepared Geometry and design elements to officially create a League of Legends-style Thumb control.
Before we begin, we need to delete the temporary Ellipse that we defined earlier as a template for the Thumb. So, remove all parts of the Thumb definition that contain Ellipse.
The Thumb we just removed was a temporary template that was defined directly by extending the Track, but this time we'll implement it with neat resource management via StaticResource.
Define a new Thumb template:
[x] Implement a Riot-style thumb and refine resources
On top of CustomControl, XAML resource management is actually pretty straightforward. Since resources have been physically separated via Generic.xaml, you can continue to manage them at a more granular level with x:Key. That's why we've also separated Geometry from LinearGradientBrush. These assets only need to be included in the style file of the RiotSlider control.
As a control inherited from Control, the Thumb can be designed using a template (ControlTemplate). As a result, you can create a control that implements a detailed trigger. In addition, if you want to create more detailed controls, you can further refine the thumb with CustomControl. This is very common in WPF basic controls.
Explore some knowledge. For example, controls like ToolBarOverflowPanel, although they may sound relatively unfamiliar, are actually quite numerous. These are created when more granular controls are needed on top of CustomControl, and are typically categorized in the Primitives namespace.
As a result, controls that belong to the Primitives namespace are usually included in other (CustomControl) controls. Take the ToggleButton, the representative control of Primitives, for example, which is not only the parent control of CheckBox/RadioButton, but can also be used as a control for toggles in the template of a control such as a ComboBox.
Interesting, right? These architectural concepts apply to all cross-platform technologies that share XAML. Therefore, being able to flexibly apply these concepts can also be very helpful in environments such as AvaloniaUI, Uno, MAUI, etc.
Of course, not all controls that belong to the Primitives namespace are specified as CustomControl via the DefaultStyleKey. There are also many classes that are simply encapsulated.
21. 声明 Thumb 资源
Finally, declare the Thumb as a resource for use in the Track via StaticResource.
To add a Thumb resource:
[x] Define the Thumb style that contains the template with the Thumb resource connection
This part is described in detail in the tutorial video, if the syntax does not feel very natural, it is recommended to refer to the video.
Now, all you need to do is use the resourced thumb in the track.
Define a thumb succinctly in a track:
[x] 使用 StaticResource 连接替换现有 Thumb
<Track Thumb="{StaticResource SliderThumb}"/>
Using a Thumb in the form of a Resource can greatly reduce the amount of code when defining a Thumb in a Track. In addition, managing resources in this way helps to have a clearer grasp of resources as a whole and is one of the important ways to maintain the quality of your code. Therefore, it is necessary to carefully study this management method.
Proceed to the next step: Check them all
PART_
Whether the control is functioning properly.
Double-confirm
PART_
Widget Functions:
[x] PART_Track
[x] PART_SelectionRange
22. Completion RiotSlider Template (Wrap Up)
Now we'll be done with the template implementation of the RiotSlider control. In addition to this, the Jamesnet.WPF library is included, so we use JamesGrid, which can also be replaced by normal Grid.
In addition, two triggers have been added and the (ControlTemplate) template area of the RiotSlider control has been broken down into resources to manage all elements at a glance, which is a feature of this project.
Because the Slider control is implemented on top of (CustomControl), related resources can be managed in the same way as resource packages.
Confirm the final result:
[x] Testing
PART_Track
Related features
[x] Testing
PART_SelectionRange
Related features
[x] Confirm the app design elements
Although the functional part has gone through several stages of analysis and implementation, it is still in the form of:
PART_
The control is standard and checks the function again.
League of Legends style slider with WPF |
This completes the detailed explanation of the CustomControl-based development process and a review of the tutorial video, from analyzing the basic Slider controls to implementing the League of Legends-style RiotSlider controls.
23. Final Words
We took a deep dive into the WPF Slider controls from an architectural perspective. On the surface, it seems simple, but there's actually a lot to discuss, which shows how much you can learn when it comes to design with WPF. We also recommend that you watch our tutorial video, where we show you coding and explain it in detail.
WPF is a platform with a bit of history, so over the years, various development methodologies, frameworks, and component open-source libraries have evolved and changed. Mainstream evaluations and interpretations change over time. As a result, the historical experience accumulated so far can actually be the cornerstone of our technology. If we have the flexibility to judge and evaluate these histories, we can find more rich and high-quality references. The mainstream view is not always true.
This is a long review that we have written with heart for a long time, and we hope to pass it on to more people.