New Posts New Posts RSS Feed: Tour Part 2 - can you keep the grid instead of a form
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Tour Part 2 - can you keep the grid instead of a form

 Post Reply Post Reply
Author
alindzon View Drop Down
Newbie
Newbie
Avatar

Joined: 28-Jul-2010
Location: Toronto
Posts: 31
Post Options Post Options   Quote alindzon Quote  Post ReplyReply Direct Link To This Post Topic: Tour Part 2 - can you keep the grid instead of a form
    Posted: 28-Jul-2010 at 4:37am
Is it possible to show an example of how the XAML would look for the child/parent releationship if the parent remained a datagrid, and the child populated based on the currently selected Row.  I have that working with plain old silverlight, but I am not sure how to bind them together.  I am working with my customer and shipto tables, but it is basically the same thing.  I tried to to keep the syntax the same, but it did not work.

<sdk:DataGrid AutoGenerateColumns="True" Name="CustomerDataGrid" ItemsSource="{Binding Customers}" />

<sdk:DataGrid Grid.Row="1" Name="CustomerShipToGrid"

ItemsSource="{Binding ElementName=CustomerDataGrid, Path=CurrentItem.ShipToes }"/>

When I use the dataform it does work.

<toolkit:DataForm Name="CustomerDataForm" ItemsSource="{Binding Customers}" EditEnded="dataForm1_EditEnded"/>

<sdk:DataGrid Grid.Row="1" Name="CustomerShipToGrid"

ItemsSource="{Binding ElementName=CustomerDataForm, Path=CurrentItem.ShipToes }"/>

I am assuming the path is the problem.
 
Also if you wanted to keep the grid instead of the dataform, how would the add and delete methods change?  Buttons could be added to allow add and delete.  In the case of simple tables why not edit, add and delete right on the grid?
Back to Top
WardBell View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 31-Mar-2009
Location: Emeryville, CA,
Posts: 338
Post Options Post Options   Quote WardBell Quote  Post ReplyReply Direct Link To This Post Posted: 28-Jul-2010 at 3:33pm
BINDING QUESTION:
 
Quick thought ... did you try Mode=TwoWay on the binding?
 
ItemsSource="{Binding ElementName=CustomerDataGrid, Path=CurrentItem.ShipToes, Mode=TwoWay }"/>
 
Give that a try and let us know.
 
ADD / DELETE BUTTON QUESTION
 
Straight up: I dislike editing in grids. Terrible user experience unless the workflow really is like a spreadsheet where you're typing values into columns, heads down, as fast as you can.
 
99% of editable grids I see scream "we don't really know what the user should do so we threw everything onto the grid and hope he/she knows what to do".
 
I do like a ListBoxView where you shape the experience and engage the editing session, one item at a time, with an easy gesture.
 
But you didn't ask me about my taste in UI. You asked how to do it ...
 
I don't think the MS DataGrid has built in buttons like the DataForm. Yes, you could add rows of buttons. Use behaviors to wire the button clicks to your ViewModel (you could use ICommand too I suppose). Web searches will be your best guide for this kind of thing. 
 
I presume you know how to create and delete entities with DevForce. Our documentation is the place to dig in to that subject ... which can require more careful thought then you might initially imagine; there's more to it all then "new Employee()" :-)
 
You might save some time by looking at 3rd party grids which have buttons and other nice features. Could be money well spent ... unless your time is free.
Back to Top
alindzon View Drop Down
Newbie
Newbie
Avatar

Joined: 28-Jul-2010
Location: Toronto
Posts: 31
Post Options Post Options   Quote alindzon Quote  Post ReplyReply Direct Link To This Post Posted: 28-Jul-2010 at 3:47pm
I looked at the third party grids, and they all seemed to either slow things down, or move the filters to the local dataset rather than the server, which only makes sense if you are fetching the whole table.  I would consider one if you had a working relationship such that your data management and their grid were a well documented and complimentary pair.  Do you have any grids you actively support?
 
I really like being able to have users enter characters into filters with instant results, very impressive and efficient.
 
I also like being able to edit and delete right in the grid, and to add with a popup that uses a Dataform or something.  Its really for backend data management by staff rather than for an end user experience.  I will need to learn more about ListBoxView. 
 
 
Back to Top
alindzon View Drop Down
Newbie
Newbie
Avatar

Joined: 28-Jul-2010
Location: Toronto
Posts: 31
Post Options Post Options   Quote alindzon Quote  Post ReplyReply Direct Link To This Post Posted: 28-Jul-2010 at 4:42pm
Tried adding the mode=twoway and it did not work.
The top grid still operates as expected, the bottom does not show anything, not even headings.

ItemsSource="{Binding ElementName=CustomerDataGrid, Path=CurrentItem.ShipToes, Mode=TwoWay}"/>

Any other thoughts?
Is CurrentItem a correct path when you are pointing to a datagrid and not a dataform?  Perhaps that is the problem?
 
 
Back to Top
alindzon View Drop Down
Newbie
Newbie
Avatar

Joined: 28-Jul-2010
Location: Toronto
Posts: 31
Post Options Post Options   Quote alindzon Quote  Post ReplyReply Direct Link To This Post Posted: 28-Jul-2010 at 5:03pm
I was right the issue was CurrentItem - which means nothing to a datagrid.
I hunted and found SelectedItem which is the closest equivalent, now the code works.
 
 
So your code works exactly the same way with a datagrid, as long as you use SelectedItem instead of CurrentItem, cool.
 
 
Back to Top
WardBell View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 31-Mar-2009
Location: Emeryville, CA,
Posts: 338
Post Options Post Options   Quote WardBell Quote  Post ReplyReply Direct Link To This Post Posted: 28-Jul-2010 at 5:34pm
Oops. I forgot about that switch from "CurrentItem" to "SelectedItem".  Thank you, Microsoft!
 
And thank you, "alindzon", for digging that out. I should have looked at my own code samples. The "Mode" attribute is the frequent cause of my binding troubles so it came immediately to mind.
 
Looking at the output window when running in the debugger ... and in WPF ... often reveals binding failures. It may work in SL too but my memory is hazy on that. Still, there really should be better way to tell when something is going wrong there.
 
A data binding feature, new in SL 4, can help you find binding troubles. It's the "FallbackValue". Here it is in action.
 
    <TextBlock Text="{Binding Name, FallbackValue='(Oops)'}" />

The TextBlock will display '(Oops)' when the binding fails. Not sure that would work for a collection binding such as yours but it may provide some relief in other cases.

Back to Top
WardBell View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 31-Mar-2009
Location: Emeryville, CA,
Posts: 338
Post Options Post Options   Quote WardBell Quote  Post ReplyReply Direct Link To This Post Posted: 28-Jul-2010 at 5:44pm
I don't have a 3rd party grid recommendation. As I said, I'm steering clear of editable grids these days.
 
You wrote:
 
"I really like being able to have users enter characters into filters with instant results, very impressive and efficient."
 
Great. Do you have any advice or sample code that you'd like to share with our audience? I'm sure they'd love to see it.
 
You wrote:
 
"I also like being able to edit and delete right in the grid, and to add with a popup that uses a Dataform or something"
 
I understand. I wrote UIs like this for years. It's in my blood. I'm trying to learn new habits.  The "pop-up" is really distracting noise when you think about it. I much prefer to have an editor "swim" into view, pushing previous content aside. Less abrupt and I don't lose the context from which the editor was launched.
 
If the editor is too big for that approach, I like to see the editor view animate in and the table go disabled-semi-transparent behind it. The editor view is not a window; it's just another design user control made visible (and draggable) that appears to overlay the table. 
 
Or I might "fly in" the editor from the right.
 
I'm looking to the phone (iPhone, Android, WP7) for some of these new UI patterns.
 
I know it seems like we don't need them ... or can't afford them  ... in business/internal apps. But once you get the hang of Blend, they're no more difficult than the pop-up window (sometimes LESS difficult to code) and they can really improve end user productivity. A shame to waste all this goodness with the same old WinForms style.

Cheers - W
 
Back to Top
alindzon View Drop Down
Newbie
Newbie
Avatar

Joined: 28-Jul-2010
Location: Toronto
Posts: 31
Post Options Post Options   Quote alindzon Quote  Post ReplyReply Direct Link To This Post Posted: 28-Jul-2010 at 7:40pm
I am totally new to UI stuff, I am more a database guy really.
 
This is all very new to me.  But as soon as I saw what silverlight grids can do I got very excited. 
 
With regard to the filtering of the grid, I used the standard RIA services stuff

<riaControls:DomainDataSource.QueryParameters>

<riaControls:Parameter ParameterName="StartName" Value="{Binding ElementName=startNameTextBox, Path=Text, TargetNullValue=''}" />

</riaControls:DomainDataSource.QueryParameters>

<riaControls:DomainDataSource.FilterDescriptors>

<riaControls:FilterDescriptor PropertyPath="Company" Operator="Contains" Value="{Binding ElementName=CompanyFilter, Path=Text}" IgnoredValue=""/>

<riaControls:FilterDescriptor PropertyPath="Contact" Operator="Contains" Value="{Binding ElementName=ContactFilter, Path=Text}" IgnoredValue=""/>

</riaControls:DomainDataSource.FilterDescriptors>

Then I just put a textbox for each of these above the grid.  RIA does the rest.  As soon as you touch the boxes it works.  The ignored value keeps it from crashing when its null.  Here is the stockpanel I used for the top of the datagrid

<StackPanel Height="26" HorizontalAlignment="Left" Orientation="Horizontal" VerticalAlignment="Top" AllowDrop="True" Margin="5,0,0,0" >

<sdk:Label Content="Start:" Margin="5,0,0,0"></sdk:Label>

<TextBox x:Name="startNameTextBox" Width="150" Text="" ToolTipService.ToolTip="Company Starts With" Margin="5,0,0,0" />

<sdk:DataPager Height="26" HorizontalAlignment="Center" Margin="5,0,0,0" Name="MainPager" PageSize="20" VerticalAlignment="Top"

TextOptions.TextHintingMode="Animated" Width="200" Source="{Binding ElementName=customerDomainDataSource, Path=Data}"

ToolTipService.ToolTip="Save or Cancel Changes First" HorizontalContentAlignment="Center" FlowDirection="LeftToRight" />

<sdk:Label Content="Includes:" Margin="5,0,0,0"></sdk:Label>

<TextBox x:Name="CompanyFilter" Width="150" ToolTipService.ToolTip="Company Name Includes" Margin="5,0,0,0" />

<TextBox x:Name="ContactFilter" Width="150" ToolTipService.ToolTip="Contact Name Includes" Margin="5,0,0,0" />

<Button Content="Save Changes" Height="26" HorizontalAlignment="left" Background="Green"

x:Name="SaveChanges" VerticalAlignment="Top" Width="100" Click="SaveChanges_Click"/>

<Button Content="Add Customer" Height="26" HorizontalAlignment="left" Background="Green"

x:Name="Add" VerticalAlignment="Top" Width="100" Click="Add_Click"/>

<Button Content="Delete Selected" Height="26" HorizontalAlignment="left" Background="Green"

x:Name="Delete" VerticalAlignment="Top" Width="100" Click="Delete_Click"/>

<Button Content="Cancel Changes" Height="26" HorizontalAlignment="left" Background="Green"

x:Name="cancelButton" VerticalAlignment="Top" Width="100" Click="cancelButton_Click"/>

</StackPanel>

So my first question is how do I create input boxes like this that will work the same way the RIA parameters and filters work?  That is the next step in my test.
 
By the way I noticed that if you specify a orderby on a query with RIA it ignores it once users click on a column.  You might want to steal that idea, although I have seen your workaround and it is no big deal to use.
 
One of my ideas is to put the filter input boxes right into the grid, just under the headings, is that posible?  Can you have a custom second header row like this?  If it is please tell me how to do it.
 
I also would like to see a way to link the sizing of two grids with similar layouts so if a user resizes the column on one, the other stays in sync.  But I doubt that is posible.  The idea was to keep the address fields in the main customer grid, and the ship to grid nicely lined up.
 
I am also wondering if there is some way to detect what exact cell a user clicks on, or to get the value of that cell.  I want to start using context sensitive menus on a right click, that will vary based on the column that is clicked.  For example I store a number of links in the Manufacturer file, and someone might want to load the web page being clicked.
 
Back to Top
WardBell View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 31-Mar-2009
Location: Emeryville, CA,
Posts: 338
Post Options Post Options   Quote WardBell Quote  Post ReplyReply Direct Link To This Post Posted: 30-Jul-2010 at 12:30am

Here are some of my thoughts on these matters ... a condensation of my separate communications with alindzon ... reprised here for the DevForce audience.

I'm alergic to the RIA Services Domain Data Source (DDS) and all similar attempts to inscribe business logic in the XAML. Such logic doesn't belong there. When it's in the view, the view becomes an untestable, unmaintainable mess. I'm not saying this because it's fashionable to opine about "Separation of Concerns". I'm saying it from ugly experience trying to make sense of customer application mud balls.
 
The DDS is a terrible idea. I respect and like the people who wrote it. They know how I feel. I believe they agree with me. But their masters at Microsoft don't believe you are good enough or smart enough to write decent code. As the saying goes, no one ever went broke underestimating the intelligence of the masses.
 
Of course they are right in a way. If you keep dazzlling folks with single screen demos. If you consistently misguide them with bad practices. Sure ... they'll fall for it. And then you can say "we gave them what they wanted." No you didn't. You taught them to want the wrong thing.
 
Am I disgusted by it? Yes I am.
 
Our IdeaBlade hearts aren't that pure either. If we can't beat 'em, we might as well join them.  Because you're now trained to want this crap, we'd like to show you how to tie your DevForce EntityManager into the DDS.
 
Unfortunately, Microsoft made sure we can't; the DDS UI control only works with RIA Services' Data Context.  So (drum roll, please) we offer you our own look-alike, the IdeaBlade.Windows.SL.ObjectDataSource.  Give it a try if you want to roll this way. It's based on the pre-release version of the DDS ... the design for RIA Services in Silverlight 3. The API has changed. Our ODS hasn't nor does it support the ability to run the search as you type. We'll bring it up-to-date eventually.
 
On the other hand, if you want my advice ... avoid it. Don't use the DDS. Don't use our ODS. Follow the View-ViewModel pattern ... which is not hard at all ... and spare yourself some future pain. You'll thank me later.
 
The fact is that you can easily do what the DDS does with simple code following the View-ViewModel pattern. Much has been said about MVVM. It boils down to this: the View's job is to look good; the ViewModel's job is to do the work; binding brings them together.
 
In this context it means that the UI controls for gathering the user's criteria ... the Company and Contact to search ... those controls go in the view. The logic to incorporate the user's criteria values into a query and run that query ... such logic belongs in the ViewModel.
 
You will bind the FilterCompany TextBox to the ViewModel ... just as you would any other data value. Let the binding push the search text into the ViewModel which senses the change, constructs the query, and executes it.
 
Ok .. it's not drag-and-drop. But you get code you can understand, debug, and test. If you need more features, you can add them. It's not a black box ... like the DDS ... where the minute you stray from the ordinary you're stuck. A black box is ok if it does something hard. This stuff is easy.
 
I already confessed that DevForce does not ship with a mechanism to watch your keystrokes and run the filter query automatically as you type.
 
Although you could write this yourself, you'd rather we took a crack at it first. So we will. And we'll give you the source. Then you can take it, or leave it, or do what you want with it.
 
We haven't written it yet. I've been thinking about how it might work, using alindzon's request as a guide.
 

Suppose …

 

1.       Your TextBox is bound to the ViewModel.FilterCompany property via an attached property or "behavior" (TBD).

 

2.       Your ViewModel has a method, “FilterFoo()”, that performs the filtered query; the method code might look like

 

   var query = Manager.Foo

    .AddFilter(FilterOperation.StartsWith, FilterCompany)

    .AddFilter(FilterOperation.StartsWith, FilterContact)

 

  // your grid’s ItemSource is bound to ResultList

  Repository.ExecuteFilterQuery(ResultList, query);

 

3.       “FilterFoo” was mentioned when you attached the TextBox property.

 

How bad would that be? Is this harder than RIA Services? To my eye it’s both simple and transparent.

 

The Behavior would be pretty simple. It listens for keystrokes. When the key stroking “stops” (i.e., there have been no new keystrokes after the prescribed delay), it invokes your FilterFoo(). The only trickiness is aggregating key stroke across the several controls that participate in the filtering (e.g., FilterCompany and FilterContact textboxes). You get that when you associate each TextBox with the ViewModel filtering method.

 

AddFilter (TBD) is an extension method on IQueryable<T> that constructs the Where clause(s). It knows to skip the clause if FilterCompany is empty after trimming. You could add the Ignore list as a third parameter if you needed it.

 

This is DevForce as you know it. And you can use the Behavior anywhere. When you figure out how to trick out your grid with filter input controls, just attach the Behavior to it.

 
Dear reader ... let me know what you think.
 
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down