Issue of Prism in Silverlight about ComboBox's UpdateLayout method

Topics: Prism v2 - Silverlight 3
Sep 2, 2009 at 9:42 AM

Hi, guys,

Today I refactor my Silverlight project in Prism. I met a puzzled issue about ComboBox.

As you know, when we changed the selected item of the ComboBox, we must invoke its UpdateLayout method to refresh the control, otherwise, no change to the control. So in the normal code style, we write code like this:

cbo.SelectedItem = XXXX;

cbo.UpdateLayout();

But in Prism, we use VM patterns now, all the data are binding to the controls, including the ComboBox, so when I fire some event, the property binding to the ComboBox will update, along with the ComboBox's SelectedItem property. But I have no chance to control the ComboxBox, because I can only control the data.

Can somebody else resolve this isuse?

Sep 2, 2009 at 12:13 PM

Bearing in mind that the Presentation Model and Model-View-ViewModel are synomonous, you are running into a problem identified by Martin Fowler back in 2006 in his article GUI Architectures.  In the section on the VisualWorks Application Model (aka Presentation Model) he notes the following below figure 11:

Directly updating the widgets like this is not part of Presentation Model, which is why the visual works application model isn't truly a Presentation Model. This need to manipulate the widgets directly was seen by many as a bit of dirty work-around and helped develop the Model-View-Presenter approach.

In PRISM V2 Drop 7 there was a TopDownComposition sample that showed how you could utilize MVP and MVVM effectively - gaining the best of both worlds/patterns.   In my http://MultiTargeting.CodePlex.com project I abstracted the concept into a series of PRISMContrib libraries supporting the SL3, SL3 w/RIA, WPF and Winforms - all platforms share the same codebase using MVP and MVVM; perhaps it will give you ideas on how you can approach your requirement.

 

Sep 2, 2009 at 1:01 PM

Hi, billkrat,

I am not care about the difference between VM and PresentationModel patterns.

Now I find solution to resolve the ComboBox's UpdateLayout method, so I can update UI ASAP.

Sep 2, 2009 at 1:17 PM

Understood, I would use "a bit of dirty work-around" to meet your requirements ;)

1.  Update the View's interface to include the following - this effectively gives you access to the views controls.

     object FindName(string controlName);

2.  Update the ViewModel so that it contains a reference to the views Interface, e.g. the model would contain a property IMyView View {get; set; }.  Not knowing how you wire-up I might suggest this could be done after the View is registered.

3.  At the point in code where I need to set the combobox.SelectedItem I would do something to the following:

    ComboBox myCombo = (ComboBox) View.FindName("myControlName");

4.   Set myCombo.SelectedItem as applicable.

Please update this thread if you find a better way so it can help the next guy.

Sep 2, 2009 at 4:00 PM

Hi, billkrat,

Some steps are the same between us.

I make a small demo for it. You can download it from here: http://files.cnblogs.com/Jax/SilverlightApplication9.zip

The PrintScreen is as follow:

1.When the page loaded

clip_image002

2.I click the CheckBox, from checked status to unchecked in “China” row.

I want to make the OverflyReason field not enabled, and set the OverflyReason default value “Please select a Station”.

clip_image002[4]

 

But I try my best, the result is as follow, that is say, no update in UI, although the binding data behind is already been changed.

clip_image002[6]

Sep 2, 2009 at 4:16 PM

Great!  The demo really makes it easier.   I have some requirements I have to complete for a client but I will work on this later this evening and will try to have something for you in the morning.

Sep 2, 2009 at 5:15 PM

Hi, billkrat,

It looks like I resolve it.

As you see in my code, each row in the datagrid has a combobox, so I have set up View property for each row, that is say, entity Station. But I doubt it is a good design.

And also, about combobox, when the selected item changed, if we only write code to change the SelectedItem property, no update in UI.

So I have a try to change the SelectedIndex property, that's all right. UI update as I requied. In another word, I must bind SelectedIndex, rather than SelectedItem property.

Let me summurize the code, and upload a successful one.

billkrat, even the issue is resolved, but I still doubt on it. Please give me some suggestion for my new code, all right?

 

Sep 2, 2009 at 5:37 PM

New version project, which is successfully done: http://files.cnblogs.com/Jax/SilverlightApplication9_new.zip

The key snipper code in the entity "Station" as follows:

        void ModelPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "IsChecked":
                    if (!this.IsChecked)
                    {
                        //this.OverflyReason = new OverflyReasonInfo()
                        //{
                        //    ReasonName = "Please select a Station!"
                        //};

                        DataGrid dg = View.FindName("dgGrid") as DataGrid;
                        if (dg != null)
                        {
                            foreach (object o in dg.ItemsSource)
                            {
                                ComboBox cb = dg.Columns[2].GetCellContent(o).FindName("cboOverflyReason") as ComboBox;

                                if (cb.SelectedItem as OverflyReasonInfo == this.OverflyReason)
                                {
                                    cb.SelectedIndex = 0;
                                    break;
                                }
                            }
                        }

                        
                        this.ChargeableAircraft = "";
                    }
                    this.IsEnabled = this.IsChecked;
                    break;
                default:
                    break;
            }
        }

 

In the code above, I mark the statement to change the SelectedItem property. Because I add a reference to the View, so I can iterate the view's controls "dgGrid" and set the SelectedIndex to 0. As a result, UI updates with no problems.

Hi, billkrat, could you give me a binding syntax, make UI update automatically, rather than handling the controls manually?

Sep 3, 2009 at 1:00 AM

Very nice Jianqiang :)

[Jianqiang] could you give me a binding syntax, make UI update automatically, rather than handling the controls manually

In WPF I'd use triggers, however Silverlight has limitations as highlighted by Rocky Lhotka in this blog entry http://www.lhotka.net/weblog/SilverlightTriggers.aspx.    His hack will require Expression 3 (which you can download w/trial period).   Personally, I'd take the simple route and manually update.