WPF How to get a UserControl to inherit a Button? - wpf

I created a UserControl which consists of a couple ellipses and labels. I added it just fine to another form and things were looking pretty snazzy.
Then I went to start adding some event handlers and discovered that the control I made did not expose a Click event. Oops. Easy to fix, right? Just go back to the code-behind on the UserControl I made and let it inherit Button.
Unfortunately, doing this caused a "Partial declarations of MyControl must not specify different base classes" message. This came as a surprise since I haven't declared any other base classes. Searching for the Partial in question returned no results either.
Is there a way to defeat this issue? If not, what would be the easiest workaround here? My goal is simply to get a Click event on the UserControl.

Yes, you've declared other base classes :) Just trust compiler :)
When you writing <UserControl ...></UserControl> in XAML, you are subclassing UserControl. If you want to subclass a Button, use <Button ...></Button> instead and ": Button" in code-behind file.
But I'm strongly encourage you to not subclass Button, its an overkill for you task. You can use MouseLeftButtonUp event instead of the Click event.

Related

WPF Listview touch issue on window 10: "an event of another datatemplate is triggered while it may not happen"

When using a WPF application on windows 10 with a touchscreen we encounter an issue with the listview. When working with a mouse it works fine.
We have created a simple test-project, which is used to simulate the problem on windows 10 and can be found on GitHub. A ticket is also created on MSDN
In short below a summary of the technical setup:
We use a grouped listview, and for each group, a togglebutton and
another (inner) listview.
The inner listview uses an ItemTemplateSelector binded to an
Datatemplate selector, to choose an datatemplate.
There are 3 datatemplates (checkbox, numeric, text) that will be
choosen based upon the type property of the bounded model.
Each datatemplate has a stackpanel. The stackpanel in the text en
numeric datatemplate is wired to an PreviewMouseDown event.
Important, the stackpanel in the checkbox isn't wired to an event.
This works in general well, however sometimes, when touching the checkbox, the
PreviousMouseDown of another template is triggered.
I would expect that this behavior may not happen, is that correct?
We found a workaround (*) for this issue but we didn't find the root
cause.
Why is the event of another template triggered?
I'm starting to believe that this could be an issue with WPF Listview
and touch behavior?
(*) If we know that sometimes an event is triggered from a wrong template,
we verify every event whether that event is originated from the right template and if not we do nothing.
Below you can see when tapping quickly on the checkbox the clickevent get's triggered.
Below more details of the code:
The datatemplates and the selector
The grouped listview with the inner listview and the itemtemplate selector
Below the code behind and the handler for the PreviewMouseDown event
Below an overview of the steps we have been taken in order to resolve
it, but none lead into a solution.
Since WPF is supporting touch and a touch on a screen is also "translated" into a mousedown event, I don't see a problem why not using a previewMouseDown event on a touch screen. I also didn't find any offical documentation of Microsoft in not doing this.
Anyway, I could no longer reproduce the problem that a touch on listviewitem is invoking another previeuwMouseDown event of a template of another listviewitem in the list by ....
Changing the PrevieuwMouseDown event by a Touchdown event!
I am glad to find a solution, however based upon many online searches, I feel there are many issues with thouch on WPF and often it's is not clear what the rootcause is. Like in this case I found a solution by trial and error, but why the problem occurs when using previewMouseDown, is puzzling.

Deriving UIElement - how to receive focus

I created a class based on UIElement and my intention is to render it myself overriding OnRender. Rendering works fine. Next I want to implement focus management and continue with other aspects of LIFE, but overriding GotFocus and calling Me.Focus() in it don't do a single thing. I places my control on a Window with one another control - TextBox, and clicking on it doesn't do a single think. Tab doesn't set focus too, and TextBox is AcceptsTab negative. I know I will have to visualize focus somehow in OnRender to actually tell when the control is focused or not, but first I need to allow it to receive focus and that's where I struggle. Could you please help me out?
P.S. I tagged this with FrameworkElement because I don't have enough reputation to create a tag UIElement and leaving tags empty seemed like a silly thing to do.
Converting my comment into an answer:
I think you'd probably be better off deriving from FrameworkElement instead.

Define KeyBindings in a UserControl, but have them applicable for the whole window?

There is a number of keyboard shortcuts that I'd like to be available application-wide, regardless of where the focus currently is.
At the moment I've got those defined as <Window.InputBindings> in my Main window's XAML.
All is good, but...
The Ribbon is encapsulated as a separate UserControl, and all the shortcuts are, naturally, related to the buttons that are in that Ribbon.
Consequently, I don't really like the smell of having 2 pieces of application logic dealing with the same functionality spread across the 2 classes.
Ideally, I would like to define the KeyBindings as <Window.InputBindings>, but in the UserControl, not in the window. Obviously, that cannot be done with XAML syntax, but only <UserControl.InputBindings> - alas, that would make them available only when the focus is on the Ribbon (which means never).
Any suggestions?
Thanks,
Alex
In the constructor of your control or in its Loaded() event handler, have it find the window in which it stands (use VisualTreeHelper.GetParent(this) recursively until GetType is Window...), then add the InputBindings you want to that window.

How to make custom WPF ContentControl that supports drag-and-drop at design time?

I want to create custom WPF control that has a single "child" control inside. Subclassing ContentControl or UserControl works, but has one flaw: these controls don't work in designer mode.
By "don't work" I mean this scenario: suppose I have a Canvas with my custom control in it. I want to put, say, a Button inside my control. I drag it from the toolbox, and it appears inside my control. However, XAML view shows that the new button actually belongs to Canvas, not to my control.
I can place it inside my control by manually editing XAML, but I want the designer to work too.
Interestingly, when I subclass Canvas, Grid or Panel, designer works as expected. However, these controls have many children, which is not what I need.
How can I make a single-child control that works in designer?
how about inheriting from Border? that way you could spare yourself the hassle with Designer Extensibility
I had the same problem with a content control I am writing and found an easy solution on this
StackOverflow thread.
Just implement the HitTestCore method:
protected override System.Windows.Media.HitTestResult HitTestCore(System.Windows.Media.PointHitTestParameters hitTestParameters)
{
return new PointHitTestResult(this, hitTestParameters.HitPoint);
}
I also had a similar question here.
But after digging and digging it seams that the real answer is "NO", there isn't any official way to support dragging controls straight into a custom Content-Control at Design-Time, even implementing 'HitTestCore' as Stephan's answer suggests, does not enable drag&drop at design-time for ContentControl.
For such purposes you should consider inheriting from either Grid or Panel (to allow multiple child controls), or Border (to allow single child).

The bast way to track "modified" of a control?

I have a usercontrol which may contain many different kind of controls (e.g. button, textbox, combobox or checkbox). I need a generic way to track if anything has been changed. In most cases I don't care about the details (ie I don't need to know which textbox has changed). When I saw EventManager.RegisterClassEvent, I thought this would be my solution, but soon I realize it's not. This problem is that it's fired too much. For example, if I have a button and a combobox in the same control, the button.click event is also fired when I hit the combobox dropdown.
In WinForms, I had to loop through all controls in the usercontrol and subscribe to appropriate event (e.g. TextBox.TextChanged, or ComboBox.SelectedIndexChanged), it's tedious but works. I hope there is a better and easier way to do it in WPF.
Routed events:
<UserControl x:Class="..." TextBoxBase.TextChanged="UserControl_TextChanged"
Selector.SelectionChanged="UserControl_SelectionChanged"
ToggleButton.Checked="UserControl_Checked"
ButtonBase.Click="UserControl_Click" />
You can Put this checking to validate the e.source in the UserControl_Click event to handle this
If(e.Source.GetType()==typeof(Button))
{
// your code
}

Resources