Need to find out which MdiChild is holding the currently active control - c#

I have an MdiContainer with 4 children inside.
Each individual child has a number of label which are styled as squares.
There are 3 rows featuring 3 squares per Child (so 3x3).
The labels are dragable from one child to another.
Each MdiChild has a StackPanel which is used to contain the rows.
When I perform a drag or a drop, i'd like to know which MdiChild were the ones involved in the drag(the origin) and the drop(the destination child).
I'm just having trouble figuring out the code to do so.
I've tried using visualtreehelpers and getparent but they haven't done the trick. Most pages I could find through googling deal with forms whereas i'm working in WPF.
Edit 1:
When testing to see if I was getting the answer I wanted, I used this code
string TheActiveMdi = Container.ActiveMdiChild.Name;
where "Container" is the name given to my MdiContainer.
For some reason the value put into the variable is just whichever is MdiChild is the last one written in my Xaml code, so it's not returning an accurate value. I have that code placed in my Drop event method.
Edit 2:
Within the drop event method, this code will allow me to access the label which was dragged:
Label sourceLbl = e.Data.GetData("System.Windows.Controls.Label") as Label;
If I use this code, I can access it's parent, which is a Stackpanel:
string LabelsParent = myObject.Parent.GetType().ToString();
MessageBox.Show(LabelsParent);
This tells me that it's a Stackpanel.
However what confuses me is that if I try to print it's name in a Messagebox:
MessageBox.Show(LabelsParent.Name);
then it simply returns "Stackpanel" whereas if I do the same with sourceLbl:
MessageBox.Show(sourceLbl.Name);
then it will in fact print it's name, which in this case is "testSquare"
Can anybody explain this or help me with my initial problem?

Related

How make an area on win form scrollable?

Items like below have to be accommodated on a specific area on WinForm.
"Order 1 ------------ Time Left: 00:20:00"
"Order 2 ------------ Time Left: 01:30:20"
We should be able to perform the following action on the each order:
Each item will occupy not more than one line. As the area specified
for it on the win form is limited, as more items comes in, I want to
make the area scrollable.
According to the time left the background color of the line should also change.
There is a DONE button next to it. So, if the item is selected and DONE is pressed, the item is moved off the list.
My question is what C# Form control can be used for it. I was thinking of labels, but how to make the area scrollable if there are many of them. If not labels, what else is suggested?
As suggested in comments, you can use grid, but in case it does not suits your requirements, this is like something what you can do -
Create a custom user control which will have a label control for your order detail and a Done button. Something like this (sure you will design it better!). The label will be empty initially and you will pass then from outside, using a public property for example, while creating the control.
Define an Event on this control, and raise this event when the Done button is clicked. This is required for your main form to know that when to remove this user control.
Add a FlowLayoutPanel to your main form. This will be the container for your user controls. Make sure to set the following so that the controls are created as desired
this.flowLayoutPanel1.FlowDirection = FlowDirection.TopDown;
this.flowLayoutPanel1.WrapContents = false;
this.flowLayoutPanel1.AutoScroll = true;
Now you can start adding your custom control to this FlowLayoutPanel, either by loop or the way you like. The control will added in linear way, one in each line, and you will also get scroll it it exceeds the given space.
Make sure to define event handler for the control, so that you know when to remove the control. And of course you can set other properties like back groung color etc. That's not going to be any problem.

WPF App with responsive design

I want to make a WPF app which has a different position of its controls depending on the size of the window.
If MainWindow has Width above, let's say 500, then I want my Grid to be 2x2, and if it's below 500, then 4x1 (4 Rows, 1 Column).
First I made 2 Grids, one 2x2, the other 4x1. I have 4 different UserControls, which represent View part of the MVVM. I thought I'd use VisualStateManager with 1 group, which has 2 states, one for defaultGrid, the other for narrowGrid. First state sets Visibility of the first Grid to Visible, and the second to Collapsed, and the other state reversed (Do I even need them both to do that?). I put GoToElementState in the handler for SizeChanged event. I saw this in a book, but they didn't use UserControls, instead they just copied all the controls from the first Grid into the second one and changed the Row and Column properties for each control. I thought that it's possible for 2 different Grids to share 1 UserControl (that was actually the only reason why I put a dozen or so controls/elements in those 4 UserControls in the first place), but so far I've found that that's not possible (although I could be wrong here).
Now, for some controls I guess I don't mind that I technically have 2 instances of each UserControl, because the bindings make them synchronized, but if I type something in the TextBox and change the window size/visual state, then in "that same" TextBox I have different text.
I've come to the conclusion that I don't need VSM at all and that I don't need any other Grids besides the root Grid. In the handler for SizeChanged I've made rootGrid be either 2x2 or 4x1, depending on the window width. In MainWindow.xaml.cs I've also made those 4 UserControls private fields and instantiated them. They are changing their Row and Column properties according to window width. By doing that I now always have only those 4 UserControl instances, that just change their position in the app. (I don't need multiple instances of any of those UserControls).
What I want to know is: Is there any better/more elegant/possibly conventional way of doing this, that I haven't found?
I had the idea of making just 2 UserControls (2 Views) and using VSM to represent them. Both Views would bind to the same properties of the ViewModel. "Synchronization" of inserted text in the TextBox or selected item of a ComboBox would then be done, for TextBox for instance, by binding the Text property of a TextBox, of the first View, to the Text property of a TextBox of the second View. But this doesn't seem like a better alternative.
I also had the idea of making custom converters for Row and Column bindings of UserControls, but that seemed even worse.
Btw. I'm using C#, VS 2013 and Windows 7. I know UWP have interesting stuff with AdaptiveTriggers in VSM, but I haven't switched to UWP yet, I just started playing with WPF a month ago.
Also I can't use WrapPanel because I need these controls in exactly 2x2 or 4x1 grids. And I can't use UniformGrid because I need them in specific order.
Any input on this would be appreciated.

Windows Store App: prevent duplicate code in two almost identical User Controls

So I've got two User Controls in my Windws Store App, that look and work almost the same:
Control 1 http://image-upload.de/image/FbKYsa/319b71644f.png
Control 2 http://image-upload.de/image/Hd9eMW/b78fca7c85.png
The events and event handling on the controls is identical, the only difference is that the second control has an additional ComboBox as you can see.
How can I prevent code duplication and doubled work whenever I change some functionality?
I tried to pack the identical controls into a resource dictionary but could not figure out how to access the control elements in the dictionary's code-behind.
As far as I know I also can't derive the second control, since the first uses XAML.
My last idea would be to use only one class and give a flag to the constructor to add a ComboBox if needed. But it just doesn't appear to be the right way. Any suggestions?
I have just done something similar on a app. My functionality required two text boxes for password entry and the OK, Cancel buttons to be available in both controls, however one of the controls also needed to display Radio Buttons for encoding types (these buttons were in a StackPanel). I added a parameter to the constructor as shown below:
public PasswordInputBox(bool isForImage)
{
this.InitializeComponent();
if (isForImage)
//initialize actions for that part of the EmbedTypePanel;
else
EmbedTypePanel.Visibility = Visibility.Collapsed;
}
Then if you need the control with the extra combo box you can initialize it, else you just collapse it so the user is none the wiser.

How to reset all items in a groupbox, but not any items outside said groupbox?

I'm working a WPF application which has a number of groupboxes, each containing 3-4 controls a piece. Each of these groupboxes contains a reset button.
Instead of explicitly writing a line for each item the groupbox reset buton should reset is there a way to have the reset button only reset all items for the groupbox it's contained upon?
When researching this issue I found the following post which seems relevant but I'm unsure how to extend Nathan's answer to do this: What is the best way to clear all controls on a form C#?
You can use this question as an source of methods you need.
First of all you need to find groupbox that contains button. To do that use sender argument form click event it is reference to button that was clicked and call FindVisualParent method from one of answers in that question. This will give you groupbox.
Then Find all ui elements by FindVisualChildren<DependencyObject> method. This will give you super set of controls that are to be cleared.
Then it is just a loop over this as in question that you referenced. Note that that question was intended for winforms not wpf so you will have to revise the controldefaults dictionary which handles grouping controls ~(Panel GroupBox) which is not needed here (and would not work in wpf).
You might add a TAG to each control telling which property is beeing edited in the control, and then on reset press, you travel up the button to find containing GroupBox, then down to find all controls contained in this GroupBox, and then you find, with the TAGs, the name of the properties that needs reset. You then reset the properties using Reflexion.
Maybe an issue is that the default value might not be obvious. But you could store the default values for all your bindings in a static object, and copy the value of the property for this reset object into the current status object.
Rq : you could also use reflexion to get the bindings for all control of current GroupBox, and then get the bounded properties from the binding, so no need for a TAG. BUT if a control has several bindings, you won't know which one to reset. In my case, controls within GroupBoxes have also a color binding to indicate wether they have default value (green) or non-default (red), hence the need for a TAG. (BUT the color indicator are read-only so reflexion could, in fact, also be used with a little more use of Reflexion... was just too lazy to change a working logic when i saw that :-) )
I don't know about your bindings so obviously i cannot tell what's best, i hope this thoughs can help.

Getting Dynamic (Runtime) Buttons in WP7 to Associate with Objects

I am creating an interface for an XNA game and can't seem to figure something out. I'm new to programming, and feel like I have to be missing something obvious.
I'm creating a grid of levels, much like something you'd see in Angry Birds.
The number of levels will be variable, so I don't want to statically program them.
All of the buttons I use for level icons are created dynamically at runtime, based on a list of level objects. As I create the buttons I set up all of the click events to point to one method that is supposed to determine which button they clicked on, and load that specific level.
My problem is I can't seem to figure out a reliable way to actually tell which button they clicked on and associated that with one of my level objects in the list. I feel like I must be missing something extremely obvious.
Things I've tried so far:
As I generate the buttons dynamically I add them as children to a grid. So I tried using the index number of the sender as the index number in my list of levels (because they should both have the same number of elements).
For example:
App.CurrentLevel = PuzzleLevelsGrid.Children.IndexOf(sender as Button);
This worked great the first time I navigate to the level picking screen, but whenever I come back to it the children of my grid gets reset to a count of 0 for some reason, so it breaks down.
I've set break points and I can't explain how it gets set to 0. I load the children in my onNavigatedTo(), and sometime between the end of that and me pressing a button to load a level it gets wiped.
The other thing I tried was setting up a button object inside my actual level object, then when dynamically creating the level buttons I actually make changes to the button property in the appropriate level.
Then when I need to find out which button was the sender I just loop through all levels and match the sender to the button property. This method actually worked pretty well... until I started trying to load my levels using a background worker thread. The worker thread can't deal with the Button because it's a UI thread thing, and crashes.
Like I said, I'm a new programmer, so I welcome any and all feedback.
Thanks in advance.
The button, like almost every UI control, has a "Tag" property. This property has been designed for you, and only for you, so that you can put any value you like to identify the control.
For instance, you can put your level object in the Tag property of the button, then just read this value back in the click event.

Categories