I'm transitioning to using WPF after using WinForms for 6+ years. Previously, using On_Paint, and drawing with Graphics and Brushes and the like, I've created custom UI elements like the below:
I'd like to duplicate this look using WPF but I'm not sure where to begin or how to do it. Thanks for any help.
The basic answer is that you need to override the ControlTemplate for the button you are styling (do this in a resource for code reuse!).
The basic format would be:
<Window.Resources>
<Style TargetType="Button" Key="MyAwesomeButtonStyle">
... Bunch of stuff including control template
</Style>
</Window.Resources>
<Grid>
<Button Style="{StaticResource MyAwesomeButtonStyle}"/>
</Grid>
To get a starting point for what the existing control template looks at, look at MSDN. For a button specifically, look at Button Styles and Templates (you can get there from the first link by scrolling down a little and clicking the "Button Styles and Templates" link).
To match your picture, you will likely need to replace the wrapping Border element with as simple Grid and add a Path to get the parallelogram shape. RadialGradientBrush can be used for the background of the path to get the color effect.
Without a more narrow question, its hard to say specifically what you need (without taking the time to just figure out the template), but my advice would be to put the existing control template into your program and use it as an override for one of your buttons. Then modify pieces to learn what they do/affect. Finally, modify the correct pieces to look like you want.
Basically, trial and error is probably your best bet as far as learning how to modify/write these are concerned.
When delving into WPF, it's best to forget everything you know about Win Forms and just pretend you're learning how to develop UIs for the first time. Pretty much everything is different, so expect a good year or so of study and work before it really starts to gel.
You can do a lot with Control Templates, though your particular controls are complex enough in appearance that hard-coding the Paths for the borders may be a bit awkward. You can get something close to the old GDI way of doing things using DrawingVisual, which lets you define vector graphics in code.
Note that you even if you did use a DrawingVisual to get the particular look you're after, you'd still probably want to use it inside a ControlTemplate for Button. This way you can take advantage of all the code that's already been written for Button and anybody using your template doesn't have to change out their Buttons for custom controls; all they have to do is apply your template to change how it looks.
Again, this is a deep and complex topic, so expect to do a lot of reading/tinkering before you have all of the concepts down. Best of luck and happy coding; WPF is well worth the pain of entry.
Related
I'm trying to make a custom Slider inside a UWP app, which should look and function somewhat like the scroll in Windows 10 built-in Photos application:
There are two main features which exist in this screenshot, yet I couldn't find a way to implement myself:
All the positions within the same range in the slider/scrollbar, should have the same tooltip value. In the screenshot example, you can see that all photos within a specific range of the slider (between two ticks) show the same tooltip, which is the name of that month.
The gaps between the ticks aren't always the same. In the screenshot example, they rely on the amount of photos taken in each month, relatively to the total amount of photos.
I have found that in WPF, it's quite easy and straight-forward to set custom values for the ticks on a Slider (see here), but in UWP these attributes seem to be gone. Also, couldn't find anything about it in the official docs. I did notice there's a UWP control called TickBar, but couldn't find any examples in order to understand if it's relevant for my question.
Am I missing something, or is it really not possible to achieve such UX without making my own fully-custom UI Control?
It's not a Slider control. If you want to make such a control, you would have to do a lot of customization. You might need to make a UserControl. This UserControl nees some basic UWP controls to make it look like the MS Photos app.
For example, you might need an custom ItemsControl(the StaggeredPanel looks very similar) to manage the layout of pictures in the page, and customize the ScrollBar, use two ItemsControls to show the Year/Month on the right side. You also need some label to show the text when you pointer move on the ScrollBar, the label might be the TextBlock control etc. You also might need some animations.
Anyway, to make such a control, you need a lot of basic knowledge and do a lot of customization. It's complex. You could submit a Feature Request on WPDev UserVoice.
Alright, so I'm trying to figure out the best way to accomplish this for my rather unique case. I have a fullscreen WPF application where controls are added to a Grid dynamically and the user is given the option to freely move/resize them. The controls can be individually moved or resized anywhere on the parent Grid but I have prevented them from overlapping via their MouseMove events. They also cannot be moved outside of their container. Since the app will be running on machines with different monitor sizes, I need to take that into consideration when making the original layout. I have an initial layout that I would like to use, but it would seem that I'm out of options:
I first tried using rows and columns just to (initially) place the controls that are added. This method places them correctly but becomes a problem when I need to move or resize the elements because the control is already assigned to a particular row and column. I could try to use this method and then remove any rows/columns after placing the controls, but I don't think that would work well.
I've also considered a Viewbox, but that's not practical in my case for fairly obvious reasons (as it merely resizes the controls to fit the screen). I'd prefer not to use this because I would only need it to standardize my initial layout. That's it. I also don't want to mess up any text that will be displayed on the window.
So yeah, this is more of a "best practice" question because any solution I can think of would not look very professional or elegant. Feel free to ask any questions if you need clarification.
Edit: As an additional note, I'd prefer to stick with a Grid as opposed to a Canvas as my container.
Edit 2: Just to be clear, I would not need the specific (inital) layout after the first launch. When the program exits, the layout (Margins, Width & Heights, etc. for each element) is saved to a file to use for the next launch.
I've developed a number of kiosk/interactive applications using WPF. If you are trying to show the element transitions (while moving), then it might be best to use a parent Canvas and bind the Canvas.Left and Canvas.Top properties. You can mimic the grid alignment, using a Canvas, if you put in place mechanisms (e.g. Manipulation/Mouse events, converters) to make sure that the Canvas attached properties adjust to the row/column offsets.
It is not uncommon at all to use the Viewbox to mitigate display differences (and your use case is not "rather unique"). You set the Viewbox to a target resolution (e.g. 1920x1080) and allow the control to fill the available space. The other alternative would be to dynamically apply a content template based on the application window size/ratio.
After looking at multiple options, I've decided to just use a calculation to (sort of) simulate the behavior of rows/columns. Because my application is fullscreen, I can take my SystemParameters.PrimaryScreenWidth and SystemParameters.PrimaryScreenHeight to orient my layout. Using a combination of universal padding (static values) and ratio-based calculations (dynamic values), I can smoothly set my initial layout.
For instance, I'm dividing the width of my monitor by 6 (rounded up to avoid decimals) and using that (minus half the control's width) as the control's Margin.Left property, centering it on a 'column' of sorts.
Honestly, my initial layout is fairly simple right now, so we'll see if this will suffice going forward. Thanks to everyone who contributed to the question, and sorry if I was unclear on what I was asking.
For this question, it would be helpful if you download these two images:
DataGrid in Main TabItem:
Very Similar DataGrid in Secondary TabItem:
If you switch them rapidly with the Windows Viewer, you will notice some subtle differences:
(a) The background color
(b) The margins
Since my objective is to make those TabItems almost identical (minus a couple extra fields in the 2nd one), I am told that all I need to do is modify the value some border and/or margin (??).
I wouldn't know where to start implementing that advice. All I need is a TabControl with the two lower tabs; they should have 3 sides with the upper being borderless, joining the upper region. Nothing else. No trembling, no shaking upon switching.
How would I go about that? Please be specific.
Does Microsoft provide XAML source code for standard controls?
TIA.
I'm using WPF and I have a problem with layouting. I have got a docked panel (non WPF, I just hosted my control inside). And when a user wishes to dock this panel on the left or the right of the screen, I need to layout my controls in one way. But when the user wishes dock this panel on top or bottom, I need to layout my controls in another way.
My question is what is the best way to implement dynamic layout of WPF controls, which depends on some conditions?
I understand, that I can use the grid and dynamically change positions of my controls inside the grid. But I am not really happy with this solution. I'm looking for a solution with no code intervention, xaml only. And in case this is impossible, at least involving minimum intervention in the code.
Thanks in advance.
You could use AvalonDock to get a docking system very much like visual studio's.
This would give your users full control on the layout they desire, and it's not too hard to implement.
But if you really want a quick way to do this, I'd recommand Binding the DockPanel.Dock property to a ViewModel value that changes upon user input (along with an IValueConverter if necessary).
For this purposes DataTemplate feature is.
The idea is to provide multiple DataTemplates and then using your custom inplementation of the DataTemplateSelector rturn right DataTemplate based on criteria.
For an example see my post regarding DataTemplates
Data Templating Overview
Use StoryBoard and change the transformation of controls
I have been using WinForms since the first framework introduced and invested a lot of time and effort in it. Now I am attempting to move to WPF and, honestly, it's not so easy.
Now I have a task, I need to implement a simple wizard, each page of which has a aligned to center group of controls. The group contains a set of buttons, four button in a row. Width of the group is constant, height is variable -- it depends on the number of buttons inside.
It's a simple task for WinForms, but I have no idea how to do it using XAML.
I have three questions:
1). Obviously, the buttons inside a group is a WrapPanel which is placed in a Grid's cell. It's simple. But how to calculate height of the WrapPanel not using code behind?
2). Which is recommended way to implement wizard? Data template or some kind of Tab Control? I probably will need to have some transition effects when switching pages.
3). Is it acceptable in WPF world to use binding as a way to repositioning controls?
Thank you in advance!
The WrapPanel will auto-adjust its height based on its contents by default. WPF is a big advancement from WinForms precisely because of the new layout paradigms. No code behind is needed for anything you've mentioned.
As for 2; there are a lot of ways to implement this, depending on how close you adhere to MVVM (if at all); I'd recommend using a styled TabControl at first (you can adjust the style to present visually the steps in the wizard as tabs, without letting the user jump between tabs), as it's easiest. Also, it's possible to bind pretty much everything to the TabControl.
3 is possible, but should be rarely needed. And I mean it.
Now then; a simple example to show you the power of WPF.
You can have in your ViewModel (if you're not familiar with MVVM google it or read any of Josh Smith's articles or book or... wow there's such a wealth of information on it I don't know which to choose) a collection of objects, let's say Step classes, which you can bind to the ItemsSource of the TabControl. The TabControl will automatically create a tab for each of your Step.
Inside your Step class, you can have a collection of items, let's say... um, Collection<Push> (I'm struggling not to use known classes like Action or Button). If the ItemTemplate of the TabControl contains anything that recognizes that collection, as in a ListBox styled internally to use a WrapPanel for its ItemsContainer, you're done: the template will show the list of Pushes in a WrapPanel and that's that.
Now, I probably shouldn't write a full tutorial here anyway, but that should get you started. Read up on DataTemplates, ItemsControl etc. (again, I'm having difficulties picking resources... Dr. WPF has awesome articles on both, but they might be a bit advanced) and you should be good to go. Just remember that there's a good reason why WPF features a lot more fluid layouts than any previous desktop technology, you should become familiar with that.