I discovered a pretty easy way to keep from pushing the right hand columns beyond the visible window, and the technique should work for any number of columns. In a two column Grid instead of setting a minimum width on the right hand column, set a maximum width on the left column. If the Grid size is fixed, that is all that would be necessary. The width to set is the desired MinWidth subtracted from width of the Grid. When the left hand column is equal to the maximum size, the splitter won't move any further right.
If the Grid size needs to be elastic, a little coding should handle that so that the MaxWidth of the left column is always equal to Grid.Width minus the desire maximum width of the right hand column.
I set 1 to max 100, 2 to max 100 and 3 to max 100 under the assumption that my grid is 300 wide. At this point there is no way to push 2 and 3 out of the view. But if I maximize my window to 600 pixel wide, now the view will be all messed up since 1, 2 and 3 will only be 100 wide each and you'll have 300 of empty space. Like wise, if I shrunk the window to 250 px, I could push 3 halfway out of view by maximizing 1 and 2.
The "correct" approach as you will see in real production apps like Visual Studio, etc. is that the min and max are limited to proportional amounts of the width (i.e. 25%) and when the frame is resized, they resize all the panes proportionally.
If the grid is 300 wide and 1,2,3 are 100 each, if you resize to 250, you should probably take 16.6 px from each pane. If you resize to 350, you should probably add 16.6 px to each pane.
You should NEVER allow a pane to run off the screen no matter what happens.
Some time ago I asked here the question how to code adding/removing columns to a Listview at runtime and 'binding columns to viewmodels'
SeldgeHammer came with this solution:
1) The WPF ListView doesn't support data binding on the GridViewColumnCollection out of the box. You can add support for this, not too difficult, but a little bit of work.
2) Once you have a WPF ListView that can support data binding on the GridViewColumnCollection, its just a matter of having your VM return a collection of columns.
3) Some gotcha's you'll run into:
a) a GridViewColumn can only be owned by one GridViewColumnCollection at a time, so you can't return a GridViewColumnCollection from your VM, you need to return an ObservableCollection<gridviewcolumn>.
b) defining a GridViewColumn in code with bindings is a major PITA, so you should devise a way to load them out of a XAML file where you'll again run into "issue a" where you can't share GridViewColumn's.
All these issues are overcomeable... basically what I ended up with was a GridViewEx class that supported two-way binding on the column collection. Remember, you are going to need to save column widths and column order .
I wanted to share a blog on this topic that I ran into the other day. I quite like the solution provided there. Sharing info never hurts right?
My current project has problems in the login dialogue, focusing on the first text box when it opens - I shall be busy tomorrow morning implementing this to see if it works - again good find - and timing was excellent.
When I was a coder, we worked on algorithms. Today, we memorize APIs for countless libraries — those libraries have the algorithms - Eric Allman
Hmm... was kind of envisioning something along the lines of a bindable version of FocusManager.FocusedElement / ElementName binding, but that would mean the VM would be tightly coupled to view control names . Not too big on having to put an attached property on x controls that I might want to set focus to (and having x public bool properties to boot). Not too sure the VM should be the one deciding focus anyways. Seems like a job for the view. I'm thinking 99% of cases can be handled in XAML with triggers .
Do you mean "event" as in raising a real event? If so, the VM raising events to the V is kinda backwards and not really much different then just exposing public properties in the VM that the V binds to.
On the drive in to work, I thought about this more... I'm now thinking something along the lines of following the .NET control model. I think using the built in VisualStateManager could possibly work. I haven't tried it, so it may be dependent on something , if so, something very similiar to it. This way, you can handle a bunch of different states (in the XAML) with a single object.
Kinda all the same... 50 public bools vs. 50 events vs. a visual state manager. I'd definitely go with some design that can do multiple things off of one property / event / whatever.
Wait, I kind of read your response as "I'm going to raise Event1" to signal that something should happen in the view. How are you going to tell the view through Event1 to set focus to 1 of 50 controls? Aren't you going to need one event for every state? What I mean is, are you defining a custom eventargs that contains which control to set focus to? The OP poster wanted to set focus from the VM to any one of those 50 controls.
Where I was headed with the VSM is that they already have a method for "switching" in the XAML based on the state. No code behind.
I think we are both trying to say the same thing in different ways LOL, that you should be able to do different things through a single property, DP, whatever.
OP sounded like he wanted to randomly set focus to random controls at random times. Otherwise, why would you need a bindable solution?
'50' as in the sense of multiple controls. If I have a dialog with 3 edit boxes, I thought OP wanted to be able to set focus to any of the 3 edit boxes.
If you wanted to do that, you'd either need a custom eventargs to pass a param, or some other object like VSM.
If you are trying to accomplish something like "hey! you were a douche and you put 24 in an edit box that only allows 50 -> 100, so I'm going to focus the edit box for you!" then I wouldn't use any of these solutions and would do it with validation templates.