Playing around with Media Center and MCML


Getting a bit off subject again, I recently started playing around at home with Media Center and MCML.  MCML basically allows you to create full fidelity applications using Media Center and, as I understand, is what most of the Media Center UI is created on.


 


It’s a rather strange programming language as the goal is to completely separate the UI (view) from the data (model).  While this certainly isn’t anything new, here it is taken to the extreme in that many things that you would normally do in code, such as events, is done in XML.  Another thing is there is no library of basic controls to build applications on – everything you need you will have to create from scratch.


 


First, a disclaimer.  I work on the Unified Communications team, not in the Media Center team – so my knowledge of MCML and Media Center is limited to the same resources you can find on the web.  While I do know a few people on that team, I have refused to bug them with my questions.


 


I will do a quick walkthrough of a (poorly written) application that I recently created.  The goal was to create a real estate searching application as my wife is studying to be a real estate agent so that was the subject that popped out first.  However, I doubt I will take this application much further than where it currently is (which is not very far).


 


The following is my opening MCML page.


 


<Mcml xmlns=http://schemas.microsoft.com/2006/mcml


      xmlns:a=assembly://RealEstateSearcher/RealEstateSearcher


      xmlns:multiselect=resx://RealEstateSearcher/RealEstateSearcher.Resources/MultiSelect


      xmlns:re=assembly://RealEstateSearcher/RealEstateSearcher.Code


      xmlns:styles=resx://RealEstateSearcher/RealEstateSearcher.Resources/Styles


      xmlns:nav=resx://RealEstateSearcher/RealEstateSearcher.Resources/NavigationPanel


      xmlns:cor=assembly://MSCorLib/System


      xmlns:me=Me>


 


  <!– Hello World UI –>


  <UI Name=Hello>


    <Content>


   


      <Panel>


        <Children>


          <Graphic Layout=Center Content=image://styles:BackgroundImage>


            <Children>


              <multiselect:MultiSelect>


                <Model>


                  <!– Test model: an option with three values –>


                  <re:MultiChoice Description=My Radio Group>


                    <Options>


                      <re:MultiChoiceItem Title=Beaux Arts />


                      <re:MultiChoiceItem Title=Bellevue />


                      <re:MultiChoiceItem Title=Bothell />


                      <re:MultiChoiceItem Title=Carnation />


                      <re:MultiChoiceItem Title=Clyde Hill />


                      <re:MultiChoiceItem Title=Duvall />


                      <re:MultiChoiceItem Title=Hunts Point />


                      <re:MultiChoiceItem Title=Issaquah />


                      <re:MultiChoiceItem Title=Kenmore />


                      <re:MultiChoiceItem Title=Kirkland />


                      <re:MultiChoiceItem Title=Medina />


                      <re:MultiChoiceItem Title=Mercer Island />


                      <re:MultiChoiceItem Title=Newcastle />


                      <re:MultiChoiceItem Title=Redmond />


                      <re:MultiChoiceItem Title=Renton />


                      <re:MultiChoiceItem Title=Sammamish />


                      <re:MultiChoiceItem Title=Woodinville />


                      <re:MultiChoiceItem Title=Yarrow Bay />


                    </Options>


                  </re:MultiChoice>


                </Model>


              </multiselect:MultiSelect>


            </Children>


          </Graphic>


        </Children>


      </Panel>


     


    </Content>


  </UI>


 


</Mcml>


 


For those of you who have used XAML the top will look very familiar.  Basically I am just imported other classes so I can use them in this file.  The UI element specified what can be considered a control or a page.  There are four possible child elements of the UI element and I use only one here – Content – which is basically what should appear on the screen.


 


Content can have only one child, so I used a panel to arrange things on the screen and then I set a background image under that.  Finally, I reference a MultiSelect object that I created and pass it in data.  The code for MultiSelect is data related so it is written in C#.


 


using System;


using System.Collections;


using System.Collections.Generic;


using System.Text;


using Microsoft.MediaCenter.UI;


 


namespace RealEstateSearcher.Code


{


    /// <summary>


    /// Handles the model for a list of values where multiple values can be selected


    /// </summary>


    public class MultiChoice : ModelItem, IValueRange


    {


        #region Private member variables


        private string _title;


        private List<string> _chosenOptions;


        private IList _options;


        private int _currentIndex;


        #endregion


 


        #region Constructor


        /// <summary>


        /// Creates a new MultiChoice instance


        /// </summary>


        public MultiChoice()


        {


            _chosenOptions = new List<string>();


            _currentIndex = 0;


        }


        #endregion


 


        #region Properties


       


        /// <summary>


        /// The description of the choice


        /// </summary>


        public string Title


        {


            get


            {


                return _title;


            }


            set


            {


                if (_title != value)


                {


                    _title = value;


                    FirePropertyChanged(“Title”);


                }


            }


        }


 


        /// <summary>


        /// The list of options available


        /// </summary>


        public IList Options


        {


            get


            {


                return _options;


            }


            set


            {


                if (_options != value)


                {


                    _options = value;


                    FirePropertyChanged(“Options”);


                }


            }


        }


 


        /// <summary>


        /// Returns a string representing the selected options


        /// </summary>


        public string SelectedOptions


        {


            get


            {


                return String.Join(“, “, _chosenOptions.ToArray());


            }


        }


 


        /// <summary>


        /// The text used to specify the items the user selected


        /// </summary>


        public string SelectText


        {


            get


            {


                if (_chosenOptions.Count == 0)


                {


                    return Resources.No_Option_Selected;


                }


                else if (_chosenOptions.Count == 1)


                {


                    return Resources.Single_Option_Selected;


                }


                else


                {


                    return Resources.Multi_Option_Selected;


                }


            }


        }


 


        #endregion


 


        #region Methods


        /// <summary>


        /// Toggles the specified selection


        /// </summary>


        /// <param name=”selection”>The selection to toggle</param>


        public void ToggleSelection(string selection)


        {


            // See if we are adding or removing the selection


            if (true == _chosenOptions.Contains(selection))


            {


                // Remove the option


                _chosenOptions.Remove(selection);


            }


            else


            {


                // Add the option


                _chosenOptions.Add(selection);


            }


            FirePropertyChanged(“SelectedOptions”);


            FirePropertyChanged(“SelectText”);


        }


        #endregion


 


        #region IValueRange Members


        /// <summary>


        /// Returns true if we have a next value


        /// </summary>


        public bool HasNextValue


        {


            get


            {


                if (_currentIndex < _options.Count)


                {


                    return true;


                }


                else


                {


                    return false;


                }


            }


        }


 


        /// <summary>


        /// Returns true if we have a previous value


        /// </summary>


        public bool HasPreviousValue


        {


            get


            {


                if (_currentIndex > 0)


                {


                    return true;


                }


                else


                {


                    return false;


                }


            }


        }


 


        /// <summary>


        /// Moves to the next value


        /// </summary>


        public void NextValue()


        {


            _currentIndex++;


        }


 


        /// <summary>


        /// Moves to the previous value


        /// </summary>


        public void PreviousValue()


        {


            _currentIndex–;


        }


 


        /// <summary>


        /// Gets the current value


        /// </summary>


        public object Value


        {


            get


            {


                return _options[_currentIndex];


            }


        }


 


        #endregion


    }


}


 


Most of this code will be of use in our actual MultiSelect control.  It implements IModelItem, which is required for all model objects.  It is not overly complex but basically allows one to keep track of which items are selected.  IValueRange is an MCML interface used by the UI to iterate through my data.  When doing data binding, it is important to call FirePropertyChanged to alert the UI that the value has changed.  The following is the MCML for my MultiSelect, which displays the UI.


 


<Mcml


  xmlns=http://schemas.microsoft.com/2006/mcml


  xmlns:re=assembly://RealEstateSearcher/RealEstateSearcher.Code


  xmlns:cor=assembly://MSCorLib/System


  xmlns:checkbox=resx://RealEstateSearcher/RealEstateSearcher.Resources/Checkbox


  xmlns:button=resx://RealEstateSearcher/RealEstateSearcher.Resources/Button


  xmlns:styles=resx://RealEstateSearcher/RealEstateSearcher.Resources/Styles


  xmlns:me=Me>


 


  <!–  Implements a multi select control consisting of multiple checkboxes –>


  <UI Name=MultiSelect >


 


    <Properties>


      <re:MultiChoice Name=Model MultiChoice=$Required />


 


      <!– These anchors represent the two places we could position  –>


      <!– our scroll arrows.     –>


      <AnchorLayoutInput Name=AlignToTop


                        Top=Scroller,0,-100 Bottom=Scroller,0,-15 Vertical=Far


                        Left=Scroller,0 Right=Scroller,1 Horizontal=Center


                        ContributesToHeight=false/>


      <AnchorLayoutInput Name=AlignToBottom


                        Top=Scroller,1,15 Bottom=Scroller,1,100 Vertical=Near


                        Left=Scroller,0 Right=Scroller,1 Horizontal=Center


                        ContributesToHeight=false/>


 


    </Properties>


     


    <Rules>


 


      <!– Bind the selected choice to the ‘Selection’ text element.          –>


      <Binding Source=[Model.SelectedOptions!cor:String] Target=[Selection.Content] />


 


      <!– Bind the sample data as a source to the repeater.                  –>


      <Binding Source=[Model.Options] Target=[Repeater.Source] />


     


      <!– Display text corresponding to the number of items selected –>


      <Binding Source=[Model.SelectText] Target=[SelectText.Content] />


 


      <!– Give ScrollingData to ScrollingHandler. –>


      <Default Target=[ScrollingHandler.ScrollingData] Value=[ScrollData]/>


 


      <!– Give Repeater to ScrollingData. –>


      <Default Target=[ScrollData.Repeater] Value=[Repeater]/>


 


      <Default Target=[Repeater.Source] Value=[Model.Options] />


     


      <!– Only show the scroll buttons if we can scroll in that direction –>


      <Binding Source=[ScrollData.CanScrollUp] Target=[ScrollUpButton.Visible]/>


      <Binding Source=[ScrollData.CanScrollDown] Target=[ScrollDownButton.Visible]/>


 


      <!– Scroll up/left –>


      <Changed Source=[ScrollUp.Invoked]>


        <Actions>


          <Invoke Target=[ScrollData.PageUp]/>


        </Actions>


      </Changed>


 


      <!– Scroll down/right –>


      <Changed Source=[ScrollDown.Invoked]>


        <Actions>


          <Invoke Target=[ScrollData.PageDown]/>


        </Actions>


      </Changed>


    </Rules>


 


    <Locals>


      <!– The ScrollingHandler which reacts to user keyboard input. –>


      <!– Turn on handing of arrow keys for scrolling (not on by    –>


      <!– default).                                                 –>


      <!– NOTE: HandlerStage must be “Direct” (which is default).   –>


      <ScrollingHandler Name=ScrollingHandler HandlerStage=Bubbled HandleDirectionalKeys=true/>


 


      <!– ScrollingData contains many ways to customize how scrolling –>


      <!– should behave. It has methods to change the current scroll  –>


      <!– position and it also reports the position. In this case,    –>


      <!– the default values are used for the sample.                 –>


      <ScrollingData Name=ScrollData/>


 


      <!– Scroll actions –>


      <Command Name=ScrollUp Description=Up/>


      <Command Name=ScrollDown Description=Down/>


 


      <ArrayListDataSet Name=DataSet />


    </Locals>


   


    <Content>


 


      <!– The scrolling list of choices–>


      <Panel Layout=Anchor>


        <Children>


         


          <!– Text element to display the usage information.                 –>


          <Text Name=TopText Content=resx://RealEstateSearcher/RealEstateSearcher.Resources/MultiSelect_Top_Title


                Color=LightGray Font=font://styles:SectionTitle  Padding=0,0,0,20>


            <LayoutInput>


              <AnchorLayoutInput Top=Parent,.10 Left=Parent,.1 />


            </LayoutInput>


          </Text>


 


          <Panel Name=SecondText>


            <Layout>


              <FlowLayout Orientation=Horizontal Spacing=5,0 AllowWrap=true/>


            </Layout>


            <LayoutInput>


              <AnchorLayoutInput Top=TopText,1,5 Left=Parent,.1 />


            </LayoutInput>


            <Children>


 


              <!– Text elements to show the choice selection.                –>


              <Text Name=SelectText Color=LightGray


                    Font=font://styles:SecondaryText Margins=0,0,0,30 />


              <Text Name=Selection Color=Red Font=font://styles:SecondaryText


                    Margins=0,0,0,30 WordWrap=true/>


 


            </Children>


          </Panel>


         


          <!– Scroll up –>


          <me:ScrollButton Name=ScrollUpButton Model=[ScrollUp]


            Image=resx://RealEstateSearcher/RealEstateSearcher.Resources/MouseNavUp FocusImage=resx://RealEstateSearcher/RealEstateSearcher.Resources/MouseNavUpFocus


            LayoutInput=[AlignToTop]/>


 


          <!– Scroll down –>


          <me:ScrollButton Name=ScrollDownButton Model=[ScrollDown]


            Image=resx://RealEstateSearcher/RealEstateSearcher.Resources/MouseNavDown FocusImage=resx://RealEstateSearcher/RealEstateSearcher.Resources/MouseNavDownFocus


            LayoutInput=[AlignToBottom]/>


 


          <!– Scrolling area –>


          <Scroller Name=Scroller Orientation=Vertical


              ScrollingData=[ScrollData] FadeSize=-5>


            <LayoutInput>


              <AnchorLayoutInput Top=SecondText,1,5 Left=Parent,.1/>


            </LayoutInput>


            <Children>


 


              <!– Content repeater –>


              <Repeater Name=Repeater Source=[DataSet] ContentName=CheckBoxItem>


                <Layout>


                  <GridLayout Orientation=Vertical Columns=1


                                          Spacing=10,10 AllowWrap=false/>


                </Layout>


                <Animations>


 


                  <!– Scrolling animation –>


                  <Animation Type=Move>


                    <Keyframes>


                      <PositionKeyframe Time=0.00 RelativeTo=Current/>


                      <PositionKeyframe Time=0.25 RelativeTo=Final/>


                    </Keyframes>


                  </Animation>


 


                </Animations>


              </Repeater>


 


            </Children>


          </Scroller>


         


        </Children>


      </Panel>


        


    </Content>


 


    <Content Name=CheckBoxItem>


      <checkbox:CheckBox Model=[Model] Option=[RepeatedItem!re:MultiChoiceItem] />


    </Content>


  </UI>


 


  <!– A list scroll button –>


  <UI Name=ScrollButton BaseUI=button:Button>


    <Properties>


      <Size Name=TileMinSize Size=0,0/>


      <Size Name=TileMaxSize Size=20,20/>


    </Properties>


 


    <Rules>


      <!– Mouse interactive only –>


      <Default Target=[Input.KeyInteractive] Value=false/>


 


      <!– No label –>


      <Default Target=[Label.Visible] Value=false/>


      <Default Target=[Background.SizingPolicy] Value=SizeToConstraint/>


 


      <!– Mouse focused styling –>


      <Condition Source=[Input.MouseFocus] SourceValue=true>


        <Actions>


          <Set Target=[Background.Content] Value=[FocusImage]/>


        </Actions>


      </Condition>


    </Rules>


  </UI>


</Mcml>


 


Here I specify other possible child elements of the UI element.  The Properties child allows me to create variables that are subject to change.  If the value is set to $Required it must be passed in but I can pass the value to any of these I desire.  If you scroll back up to the default page you will see that I pass in the value of Model, which is required.  The AnchorLayoutInput elements are just shortcuts for later and specify that those elements should be aligned to the top of the parent or to the bottom.


 


The Rules section allows me to specify bindings and event handlers.  The Default element allows me to give an element a default value.  Here I have several elements that specify the data from the C# code I showed above is used to populate a scrolling repeater element – which is how data lists are displayed in MCML.  The event handlers here handle the case of the scroll up and scroll down buttons being clicked and scroll up or down as appropriate.


 


The Locals section allows us to specify variables not subject to change through the page.  Here I have some command objects that handle the clicking of my up and down scroll buttons.


 


In the Panel of my Content element, I specify a layout of Anchor which allows me to specify the location of an item relative to its parent.  I found it a bit tricky to get the hang of but eventually my controls ended up where I wanted them.  Basically here I display two rows of text – where the first is just some static text saying what the user should do and the second displays the user’s selections.  Finally I have a Scroller item that displays the data from my model.  The Repeater is what actually handles the data and you can see below the Scroller I call a CheckBox element that I will get to shortly.  Note that even though the Scroller and Repeater handle scrolling data, I still need to add the scroll buttons myself.


 


I placed the XML for the ScrollButton element within the same file at the bottom.  It derives from the button element that I will also cover shortly.  Basically here I set some common properties for the buttons and handle mouse focusing.  I also keep it from the keyboard. 


 


The code for button is a bit simpler than checkbox so I will cover that next.


 


<Mcml


      xmlns=http://schemas.microsoft.com/2006/mcml


      xmlns:sys=assembly://mscorlib/System


      xmlns:styles=resx://RealEstateSearcher/RealEstateSearcher.Resources/Styles


      xmlns:me=Me>


 


  <UI Name=Button>


    <Properties>


      <!– The action that will be invoked when this button is pressed –>


      <ICommand Name=Model ICommand=$Required/>


 


      <!– Button label properties –>


      <Color Name=TextColor Color=color://styles:Text.Active/>


      <Color Name=TextFocusColor Color=color://styles:Text.Negative/>


      <Color Name=TextSelectedColor Color=color://styles:Text.Copy/>


      <Font Name=TextFont Font=font://styles:SecondaryText/>


      <Inset Name=TextMargins Inset=8,-2,8,2/>


      <sys:Boolean Name=CenterText Boolean=false/>


 


      <!– Tile metrics –>


      <Size Name=TileMinSize Size=0,32/>


      <Size Name=TileMaxSize Size=300,32/>


 


      <!– Images –>


      <Image Name=Image Image=null/>


      <Image Name=FocusImage Image=image://styles:ButtonFocusImage/>


    </Properties>


 


    <Locals>


      <!– Make this button clickable –>


      <ClickHandler Name=Clicker Command=[Model]/>


    </Locals>


 


    <Rules>


      <!– Bind the button’s label –>


      <Binding Source=[Model.Description] Target=[Label.Content]/>


 


      <!– Pressed styling –>


      <Condition Source=[Clicker.Clicking] SourceValue=true>


        <Actions>


          <!–<PlaySound Sound=”sound://styles:SelectSound”/>–>


          <PlayAnimation Target=[Background] Animation=animation://me:ButtonPress/>


        </Actions>


      </Condition>


 


      <!– Focused styling –>


      <Condition Source=[Input.KeyFocus] SourceValue=true>


        <Actions>


          <Set Target=[Background.Content] Value=[FocusImage]/>


          <Set Target=[Label.Color] Value=[TextFocusColor]/>


          <!–<PlaySound Sound=”sound://styles:FocusSound”/>–>


        </Actions>


      </Condition>


 


      <!– Selected styling –>


      <Condition Source=[Model.Selected] SourceValue=true>


        <Actions>


          <Set Target=[Label.Color] Value=[TextSelectedColor]/>


        </Actions>


      </Condition>


 


      <!– Hook up dynamic text style properties. –>


      <Binding Source=[TextColor] Target=[Label.Color]/>


      <Binding Source=[TextFont] Target=[Label.Font]/>


      <Binding Source=[TextMargins] Target=[Label.Margins]/>


 


      <!– Change the layout if using the “center” option –>


      <Condition Source=[CenterText] SourceValue=true


                        Target=[Background.Layout] Value=Center/>


 


      <!– Accessibility –>


      <Binding Target=[Accessible.IsPressed]            Source=[Clicker.Clicking]/>


      <Binding Target=[Accessible.IsFocusable]          Source=[Input.KeyInteractive]/>


      <Binding Target=[Accessible.IsFocused]            Source=[Input.KeyFocus]/>


      <Binding Target=[Accessible.Name]                 Source=[Model.Description]/>


      <Default Target=[Accessible.DefaultActionCommand] Value=[Model]/>


      <Default Target=[Accessible.DefaultAction]        Value=Press/>


      <Default Target=[Accessible.Role]                 Value=PushButton/>


    </Rules>


 


    <Content>


      <!– Background –>


      <Graphic Name=Background Content=[Image] SizingPolicy=SizeToChildren


                              MinimumSize=[TileMinSize] MaximumSize=[TileMaxSize]>


        <Children>


 


          <!– Label –>


          <Text Name=Label Font=[TextFont] Color=[TextColor] Margins=[TextMargins]/>


 


        </Children>


      </Graphic>


    </Content>


  </UI>


 


 


  <!– Animations –>


  <Animation Name=ButtonPress Loop=0 CenterPointPercent=0.5,0.5,1.0>


    <Keyframes>


      <ScaleKeyframe Time=0.00 RelativeTo=Current Interpolation=Log/>


      <ScaleKeyframe Time=0.08 Value=0.9,0.9,1.0/>


      <ScaleKeyframe Time=0.15 Value=1.0,1.0,1.0/>


    </Keyframes>


  </Animation>


 


</Mcml>


 


Here you can see what I mean by the fact that you have to implement almost everything yourself.  I am sorry to say now that I am running out of time to write this post so rather than leave you in the dark about the rest of the code I will just post it without explanation below.  If you have any questions about it please feel free to ask – though I can’t guarantee that I know the answer.  I should also reiterate that I am just a beginner in MCML so a lot of what I am doing is likely wrong.  But if you’d like to get a further feel for what you can do, here is the code for checkbox.


 


<Mcml


    xmlns=http://schemas.microsoft.com/2006/mcml


    xmlns:cor=assembly://MSCorLib/System


    xmlns:re=assembly://RealEstateSearcher/RealEstateSearcher.Code


    xmlns:styles=resx://RealEstateSearcher/RealEstateSearcher.Resources/Styles


    xmlns:me=Me>


 


  <UI Name=CheckBox>


 


    <Properties>


 


      <!– Command is a required parameter. –>


      <re:MultiChoice Name=Model MultiChoice=$Required />


      <re:MultiChoiceItem Name=Option MultiChoiceItem=$Required/>


 


      <Size Name=BoxSize Size=50,50/>


 


      <!– Checked box color properties. –>


      <Color Name=CheckColor Color=White/>


      <Color Name=CheckFocusedColor Color=White/>


      <Color Name=CheckHoverColor Color=White/>


      <Color Name=CheckPressedColor Color=DimGray/>


 


      <!– Label color properties. –>


      <Color Name=LabelColor Color=color://styles:Text.Active/>


      <Color Name=LabelFocusedColor Color=color://styles:Text.Focused/>


      <Color Name=LabelSelectedColor Color=color://styles:Text.Selected/>


      <Color Name=LabelHoverColor Color=color://styles:Text.Focused/>


      <Color Name=LabelPressedColor Color=color://styles:Text.Focused/>


 


      <!– Label font property. –>


      <Font Name=LabelFont Font=font://styles:SecondaryText/>


 


    </Properties>


 


    <Locals>


 


      <!– React to “click” input. –>


      <ClickHandler Name=Clicker/>


 


    </Locals>


 


    <Rules>


 


      <!– The command description is displayed by the text box. A  –>


      <!– binding is used in case the description changes at       –>


      <!– runtime.                                                 –>


      <Binding Source=[Option.Title] Target=[Label.Content]/>


 


      <!– Toggle the selected value –>


      <Changed Source=[Clicker.Invoked]>


        <Conditions>


          <Equality Source=[Option.IsSelected] Value=false />


        </Conditions>


        <Actions>


          <Invoke Target=[Model.ToggleSelection] selection=[Option.Title] />


          <Set Target=[Check.Content] Value=image://styles:CheckBoxCheckedFocus />


          <Set Target=[Option.IsSelected] Value=[Model.Value]>


            <Transformer>


              <BooleanTransformer Inverse=true/>


            </Transformer>


          </Set>


        </Actions>


      </Changed>


     


      <!– Untoggle the selected value –>


      <Changed Source=[Clicker.Invoked]>


        <Conditions>


          <Equality Source=[Option.IsSelected] Value=true />


        </Conditions>


        <Actions>


          <Invoke Target=[Model.ToggleSelection] selection=[Option.Title] />


          <Set Target=[Option.IsSelected] Value=[Model.Value]>


            <Transformer>


              <BooleanTransformer Inverse=false/>


            </Transformer>


          </Set>


        </Actions>


      </Changed>


 


      <!– Show the check when selected –>


      <Changed Source=[Option.IsSelected]>


        <Conditions>


          <Equality Source=[Option.IsSelected] Value=true />


        </Conditions>


        <Actions>


          <Set Target=[Check.Content] Value=image://styles:CheckBoxChecked />


          <Set Target=[Label.Color] Value=[LabelSelectedColor] />


        </Actions>


      </Changed>


 


      <!– Do not show the check when selected –>


      <Changed Source=[Option.IsSelected]>


        <Conditions>


          <Equality Source=[Option.IsSelected] Value=false />


        </Conditions>


        <Actions>


          <Set Target=[Check.Content] Value=image://styles:CheckBoxNonFocus />


          <Set Target=[Label.Color] Value=[LabelColor] />


        </Actions>


      </Changed>


 


      <!– Retain the check mark when not selected –>


      <Condition Source=[Clicker.Clicking] SourceValue=false>


        <Conditions>


          <Equality Source=[Input.MouseFocus] Value=false />


          <Equality Source=[Input.KeyFocus] Value=false />


          <Equality Source=[Option.IsSelected] Value=true />


        </Conditions>


        <Actions>


          <Set Target=[Check.Content] Value=image://styles:CheckBoxChecked />


          <Set Target=[Label.Color] Value=[LabelSelectedColor] />


        </Actions>


      </Condition>


     


      <!– Change color on mouse focus when checkbox is not checked. –>


      <Condition Source=[Clicker.Clicking] SourceValue=true>


        <Conditions>


          <Equality Source=[Option.IsSelected] Value=false />


        </Conditions>


        <Actions>


          <Set Target=[Label.Color] Value=[LabelPressedColor]/>


          <Set Target=[Check.Content] Value=image://styles:CheckBoxFocus/>


        </Actions>


      </Condition>


 


      <!– Change color on mouse focus when checkbox is not checked. –>


      <Condition Source=[Input.MouseFocus] SourceValue=true>


        <Conditions>


          <Equality Source=[Option.IsSelected] Value=false />


        </Conditions>


        <Actions>


          <Set Target=[Label.Color] Value=[LabelHoverColor]/>


          <Set Target=[Check.Content] Value=image://styles:CheckBoxFocus/>


        </Actions>


      </Condition>


 


      <Default Target=[Input.KeyInteractive] Value=true/>


 


      <!– Change color on key focus when checkbox is not checked. –>


      <Condition Source=[Input.KeyFocus] SourceValue=true>


        <Conditions>


          <Equality Source=[Option.IsSelected] Value=false />


        </Conditions>


        <Actions>


          <Set Target=[Label.Color] Value=[LabelFocusedColor]/>


          <Set Target=[Check.Content] Value=image://styles:CheckBoxFocus/>


        </Actions>


      </Condition>


 


      <!– Change color on mouse focus when checkbox is checked. –>


      <Condition Source=[Clicker.Clicking] SourceValue=true>


        <Conditions>


          <Equality Source=[Option.IsSelected] Value=true />


        </Conditions>


        <Actions>


          <Set Target=[Label.Color] Value=[LabelPressedColor]/>


          <Set Target=[Check.Content] Value=image://styles:CheckBoxCheckedFocus/>


        </Actions>


      </Condition>


 


      <!– Change color on mouse focus when checkbox is checked. –>


      <Condition Source=[Input.MouseFocus] SourceValue=true>


        <Conditions>


          <Equality Source=[Option.IsSelected] Value=true />


        </Conditions>


        <Actions>


          <Set Target=[Label.Color] Value=[LabelHoverColor]/>


          <Set Target=[Check.Content] Value=image://styles:CheckBoxCheckedFocus/>


        </Actions>


      </Condition>


 


      <Default Target=[Input.KeyInteractive] Value=true/>


 


      <!– Change color on key focus when checkbox is checked. –>


      <Condition Source=[Input.KeyFocus] SourceValue=true>


        <Conditions>


          <Equality Source=[Option.IsSelected] Value=true />


        </Conditions>


        <Actions>


          <Set Target=[Label.Color] Value=[LabelFocusedColor]/>


          <Set Target=[Check.Content] Value=image://styles:CheckBoxCheckedFocus/>


        </Actions>


      </Condition>


 


    </Rules>


 


    <Content>


 


      <Panel>


        <Layout>


          <FlowLayout Orientation=Horizontal ItemAlignment=Center/>


        </Layout>


        <Children>


 


          <!– The box around the check –>


 


            <Graphic Name=Check Content=image://styles:CheckBoxNonFocus


                     MouseInteractive=true Margins=0,0,5,0 MaximumSize=[BoxSize] Layout=Form>


              <LayoutInput>


                <FormLayoutInput Left=Parent,0.2 Right=Parent,0.8


                                 Top=Parent,0.2 Bottom=Parent,0.8/>


              </LayoutInput>


            </Graphic>


 


          <!– The label to display. –>


          <Text Name=Label Color=[LabelColor] Font=[LabelFont]/>


 


        </Children>


      </Panel>


 


    </Content>


 


  </UI>


 


</Mcml>


 


 


Several of these pages reference a style sheet which is defined as follows.


 


<Mcml xmlns=http://schemas.microsoft.com/2006/mcml>


 


  <!– These style names are taken from the Design Guidelines spec. –>


  <!– There should be a 1-to-1 mapping to enable easy editing. –>


 


  <Color Name=Background.A Color=133,146,148/>


 


  <Color Name=Container.A Color=191,130,130,130/>


  <Color Name=Container.B Color=191,55, 62, 64/>


 


  <Color Name=Text.Copy         Color=255,255,255,255/>


  <Color Name=Text.Active   Color=128,255,255,255/>


  <Color Name=Text.Focused  Color=255,255,255,255/>


  <Color Name=Text.Selected Color=188,255,255,255/>


  <Color Name=Text.Negative Color=255,54,57,9/>


 


  <Color Name=Accent.A Color=255,255,255/>


  <Color Name=Accent.B Color=182,206,0/>


 


  <!– Fonts –>


 


  <Font Name=MainMenuSectionTitle Font=Calibri Bold,48/>


  <Font Name=SectionTitle         Font=Calibri Bold,32/>


  <Font Name=CopyText             Font=Calibri,22/>


  <Font Name=SecondaryText        Font=Calibri,18/>


  <Font Name=TertiaryText         Font=Calibri,16/>


  <Font Name=GalleryItemSubText   Font=Calibri,14/>


 


  <Font Name=EditText             Font=Segoe UI,20/>


  <Font Name=KeyboardText         Font=Segoe UI,18/>


 


 


  <!– Shared image resources –>


 


  <Image Name=BackgroundImage Source=resx://RealEstateSearcher/RealEstateSearcher.Resources/Background NineGrid=4,4,4,4/>


  <Image Name=CheckBoxFocus Source=resx://RealEstateSearcher/RealEstateSearcher.Resources/CheckBoxFocus NineGrid=4,4,4,4/>


  <Image Name=CheckBoxNonFocus Source=resx://RealEstateSearcher/RealEstateSearcher.Resources/CheckBoxNonFocus NineGrid=4,4,4,4/>


  <Image Name=CheckBoxChecked Source=resx://RealEstateSearcher/RealEstateSearcher.Resources/CheckBoxChecked NineGrid=4,4,4,4/>


  <Image Name=CheckBoxCheckedFocus Source=resx://RealEstateSearcher/RealEstateSearcher.Resources/CheckBoxCheckedFocus NineGrid=4,4,4,4/>


  <Image Name=ContainerImage Source=resx://RealEstateSearcher/RealEstateSearcher.Resources/Container NineGrid=40,40,40,40/>


  <Image Name=ButtonFocusImage Source=resx://RealEstateSearcher/RealEstateSearcher.Resources/ButtonFocus NineGrid=4,4,4,4/>


  <Image Name=ButtonNonFocusImage Source=resx://RealEstateSearcher/RealEstateSearcher.Resources/ButtonNonFocus NineGrid=4,4,4,4/>


 


 


</Mcml>


 


Finally, here is the code for MultiChoiceItem, which is used by the MultiSelect and checkbox.


 


using System;


using System.Collections.Generic;


using System.Text;


using Microsoft.MediaCenter.UI;


 


namespace RealEstateSearcher.Code


{


    /// <summary>


    /// Handles items used in a multi choice


    /// </summary>


    public class MultiChoiceItem : ModelItem


    {


        private bool _isSelected;


        private string _title;


 


        /// <summary>


        /// True if this choice is selected


        /// </summary>


        public bool IsSelected


        {


            get


            {


                return _isSelected;


            }


            set


            {


                if (value != _isSelected)


                {


                    _isSelected = value;


                    FirePropertyChanged(“IsSelected”);


                }


            }


        }


 


        /// <summary>


        /// The description of the choice


        /// </summary>


        public string Title


        {


            get


            {


                return _title;


            }


            set


            {


                if (value != _title)


                {


                    _title = value;


                    FirePropertyChanged(“Title”);


                }


            }


        }


    }


}