Search Results

Search found 365 results on 15 pages for 'selecteditem'.

Page 11/15 | < Previous Page | 7 8 9 10 11 12 13 14 15  | Next Page >

  • Silverlight Recruiting Application Part 6 - Adding an Interview Scheduling Module/View

    Between the last post and this one I went ahead and carried the ideas for the Jobs module and view into the Applicants module and view- they're both doing more or less the same thing, except with different objects being at their core.  Made for an easy cut-and-paste operation with a few items being switched from one to another.  Now that we have the ability to add postings and applicants, wouldn't it be nice if we could schedule an interview?  Of course it would! Scheduling Module I think you get the drift from previous posts that these project structures start looking somewhat similar.  The interview scheduling module is no different than the rest- it gets a SchedulingModule.cs file at the root that inherits from IModule, and there is a single SchedulerView.xsml and SchedulerViewModel.cs setup for our V+VM.  We have one unique concern as we enter into this- RadScheduler deals with AppointmentsSource, not ItemsSource, so there are some special considerations to take into account when planning this module. First, I need something which inherits from AppointmentBase.  This is the core of the RadScheduler appointment, and if you are planning to do any form of custom appointment, you'll want it to inherit from this.  Then you can add-on functionality as needed.  Here is my addition to the mix, the InterviewAppointment: 01.public class InterviewAppointment : AppointmentBase 02.{ 03.    private int _applicantID; 04.    public int ApplicantID 05.    { 06.        get { return this._applicantID; } 07.        set 08.        { 09.            if (_applicantID != value) 10.            { 11.                _applicantID = value; 12.                OnPropertyChanged("ApplicantID"); 13.            } 14.        } 15.    } 16.   17.    private int _postingID; 18.    public int PostingID 19.    { 20.        get { return _postingID; } 21.        set 22.        { 23.            if (_postingID != value) 24.            { 25.                _postingID = value; 26.                OnPropertyChanged("PostingID"); 27.            } 28.        } 29.    } 30.   31.    private string _body; 32.    public string Body 33.    { 34.        get { return _body; } 35.        set 36.        { 37.            if (_body != value) 38.            { 39.                _body = value; 40.                OnPropertyChanged("Body"); 41.            } 42.        } 43.    } 44.   45.    private int _interviewID; 46.    public int InterviewID 47.    { 48.        get { return _interviewID; } 49.        set 50.        { 51.            if (_interviewID != value) 52.            { 53.                _interviewID = value; 54.                OnPropertyChanged("InterviewID"); 55.            } 56.        } 57.    } 58.   59.    public override IAppointment Copy() 60.    { 61.        IAppointment appointment = new InterviewAppointment(); 62.        appointment.CopyFrom(this);             63.        return appointment; 64.    } 65.   66.    public override void CopyFrom(IAppointment other) 67.    {             68.        base.CopyFrom(other); 69.        var appointment = other as InterviewAppointment; 70.        if (appointment != null) 71.        { 72.            ApplicantID = appointment.ApplicantID; 73.            PostingID = appointment.PostingID; 74.            Body = appointment.Body; 75.            InterviewID = appointment.InterviewID; 76.        } 77.    } 78.} Nothing too exciting going on here, we just make sure that our custom fields are persisted (specifically set in CopyFrom at the bottom) and notifications are fired- otherwise this ends up exactly like the standard appointment as far as interactions, etc.  But if we've got custom appointment items... that also means we need to customize what our appointment dialog window will look like. Customizing the Edit Appointment Dialog This initially sounds a lot more intimidating than it really is.  The first step here depends on what you're dealing with for theming, but for ease of everything I went ahead and extracted my templates in Blend for RadScheduler so I could modify it as I pleased.  For the faint of heart, the RadScheduler template is a few thousand lines of goodness since there are some very complex things going on in that control.  I've gone ahead and trimmed down the template parts I don't need as much as possible, so what is left is all that is relevant to the Edit Appointment Dialog.  Here's the resulting Xaml, with line numbers, so I can explain further: 001.<UserControl.Resources> 002.    <!-- begin Necessary Windows 7 Theme Resources for EditAppointmentTemplate --> 003.    <helpers:DataContextProxy x:Key="DataContextProxy" /> 004.       005.    <telerik:Windows7Theme x:Key="Theme" /> 006.    <SolidColorBrush x:Key="DialogWindowBackground" 007.                     Color="White" /> 008.    <SolidColorBrush x:Key="CategorySelectorBorderBrush" 009.                     Color="#FFB1B1B1" /> 010.    <LinearGradientBrush x:Key="RadToolBar_InnerBackground" 011.                         EndPoint="0.5,1" 012.                         StartPoint="0.5,0"> 013.        <GradientStop Color="#FFFDFEFF" 014.                      Offset="0" /> 015.        <GradientStop Color="#FFDDE9F7" 016.                      Offset="1" /> 017.        <GradientStop Color="#FFE6F0FA" 018.                      Offset="0.5" /> 019.        <GradientStop Color="#FFDCE6F4" 020.                      Offset="0.5" /> 021.    </LinearGradientBrush> 022.    <Style x:Key="FormElementTextBlockStyle" 023.           TargetType="TextBlock"> 024.        <Setter Property="HorizontalAlignment" 025.                Value="Right" /> 026.        <Setter Property="VerticalAlignment" 027.                Value="Top" /> 028.        <Setter Property="Margin" 029.                Value="15, 15, 0, 2" /> 030.    </Style> 031.    <Style x:Key="FormElementStyle" 032.           TargetType="FrameworkElement"> 033.        <Setter Property="Margin" 034.                Value="10, 10, 0, 2" /> 035.    </Style> 036.    <SolidColorBrush x:Key="GenericShallowBorderBrush" 037.                     Color="#FF979994" /> 038.    <telerik:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> 039.    <telerikScheduler:ImportanceToBooleanConverter x:Key="ImportanceToBooleanConverter" /> 040.    <telerikScheduler:NullToVisibilityConverter x:Key="NullToVisibilityConverter" /> 041.    <telerikScheduler:InvertedNullToVisibilityConverter x:Key="InvertedNullToVisibilityConverter" /> 042.    <scheduler:ResourcesSeparatorConverter x:Key="ResourcesSeparatorConverter" /> 043.    <DataTemplate x:Key="IconDataEditTemplate"> 044.        <Image Source="/Telerik.Windows.Controls.Scheduler;component/Themes/Office/Images/cal.png" 045.               Margin="3,3,0,0" 046.               Width="16" 047.               Height="16" /> 048.    </DataTemplate> 049.    <DataTemplate x:Key="SingleSelectionTemplate"> 050.        <Grid VerticalAlignment="Stretch" 051.              HorizontalAlignment="Stretch"> 052.            <Grid.RowDefinitions> 053.                <RowDefinition Height="Auto" /> 054.            </Grid.RowDefinitions> 055.            <Grid.ColumnDefinitions> 056.                <ColumnDefinition Width="Auto" 057.                                  MinWidth="84" /> 058.                <ColumnDefinition Width="Auto" 059.                                  MinWidth="200" /> 060.            </Grid.ColumnDefinitions> 061.            <TextBlock x:Name="SelectionNameLabel" 062.                       Margin="0,13,4,2" 063.                       Text="{Binding ResourceType.DisplayName}" 064.                       Style="{StaticResource FormElementTextBlockStyle}" 065.                       Grid.Column="0" /> 066.            <telerikInput:RadComboBox ItemsSource="{Binding ResourceItems}" 067.                                      Width="185" 068.                                      Margin="5,10,20,2" 069.                                      HorizontalAlignment="Left" 070.                                      Grid.Column="1" 071.                                      ClearSelectionButtonVisibility="Visible" 072.                                      ClearSelectionButtonContent="Clear All" 073.                                      DisplayMemberPath="Resource.DisplayName" 074.                                      telerik:StyleManager.Theme="{StaticResource Theme}" 075.                                      SelectedItem="{Binding SelectedItem, Mode=TwoWay}" /> 076.        </Grid> 077.    </DataTemplate> 078.    <DataTemplate x:Key="MultipleSelectionTemplate"> 079.        <Grid VerticalAlignment="Stretch" 080.              HorizontalAlignment="Stretch"> 081.            <Grid.RowDefinitions> 082.                <RowDefinition Height="Auto" /> 083.            </Grid.RowDefinitions> 084.            <Grid.ColumnDefinitions> 085.                <ColumnDefinition Width="Auto" 086.                                  MinWidth="84" /> 087.                <ColumnDefinition Width="Auto" 088.                                  MinWidth="200" /> 089.            </Grid.ColumnDefinitions> 090.            <TextBlock x:Name="SelectionNameLabel" 091.                       Grid.Column="0" 092.                       Text="{Binding ResourceType.DisplayName}" 093.                       Margin="0,13,4,2" 094.                       Style="{StaticResource FormElementTextBlockStyle}" /> 095.            <telerikInput:RadComboBox Grid.Column="1" 096.                                      Width="185" 097.                                      HorizontalAlignment="Left" 098.                                      Margin="5,10,20,2" 099.                                      ItemsSource="{Binding ResourceItems}" 100.                                      SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}" 101.                                      ClearSelectionButtonVisibility="Visible" 102.                                      ClearSelectionButtonContent="Clear All" 103.                                      telerik:StyleManager.Theme="{StaticResource Theme}"> 104.                <telerikInput:RadComboBox.ItemTemplate> 105.                    <DataTemplate> 106.                        <Grid HorizontalAlignment="Stretch" 107.                              VerticalAlignment="Stretch"> 108.                            <CheckBox VerticalAlignment="Center" 109.                                      HorizontalContentAlignment="Stretch" 110.                                      VerticalContentAlignment="Center" 111.                                      IsChecked="{Binding IsChecked, Mode=TwoWay}" 112.                                      Content="{Binding Resource.DisplayName}"> 113.                                <CheckBox.ContentTemplate> 114.                                    <DataTemplate> 115.                                        <TextBlock HorizontalAlignment="Stretch" 116.                                                   VerticalAlignment="Stretch" 117.                                                   Text="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}" /> 118.                                    </DataTemplate> 119.                                </CheckBox.ContentTemplate> 120.                            </CheckBox> 121.                        </Grid> 122.                    </DataTemplate> 123.                </telerikInput:RadComboBox.ItemTemplate> 124.            </telerikInput:RadComboBox> 125.        </Grid> 126.    </DataTemplate> 127.    <scheduler:ResourceTypeTemplateSelector x:Key="ItemTemplateSelector" 128.                                            MultipleSelectionTemplate="{StaticResource MultipleSelectionTemplate}" 129.                                            SingleSelectionTemplate="{StaticResource SingleSelectionTemplate}" /> 130.    <!-- end Necessary Windows 7 Theme Resources for EditAppointmentTemplate -->  131.       132.    <ControlTemplate x:Key="EditAppointmentTemplate" 133.                     TargetType="telerikScheduler:AppointmentDialogWindow"> 134.        <StackPanel Background="{TemplateBinding Background}" 135.                    UseLayoutRounding="True"> 136.            <StackPanel Grid.Row="0" 137.                        Orientation="Horizontal" 138.                        Background="{StaticResource RadToolBar_InnerBackground}" 139.                        Grid.ColumnSpan="2" 140.                        Height="0"> 141.                <!-- Recurrence buttons --> 142.                <Border Margin="1,1,0,0" 143.                        Background="#50000000" 144.                        HorizontalAlignment="Left" 145.                        VerticalAlignment="Center" 146.                        Width="2" 147.                        Height="16"> 148.                    <Border Margin="0,0,1,1" 149.                            Background="#80FFFFFF" 150.                            HorizontalAlignment="Left" 151.                            Width="1" /> 152.                </Border> 153.                <Border Margin="1,1,0,0" 154.                        Background="#50000000" 155.                        HorizontalAlignment="Left" 156.                        VerticalAlignment="Center" 157.                        Width="2" 158.                        Height="16"> 159.                    <Border Margin="0,0,1,1" 160.                            Background="#80FFFFFF" 161.                            HorizontalAlignment="Left" 162.                            Width="1" /> 163.                </Border> 164.                <TextBlock telerik:LocalizationManager.ResourceKey="ShowAs" 165.                           VerticalAlignment="Center" 166.                           Margin="5,0,0,0" /> 167.                <telerikInput:RadComboBox ItemsSource="{TemplateBinding TimeMarkers}" 168.                                          Width="100" 169.                                          Height="20" 170.                                          VerticalAlignment="Center" 171.                                          Margin="5,0,0,0" 172.                                          ClearSelectionButtonVisibility="Visible" 173.                                          ClearSelectionButtonContent="Clear" 174.                                          SelectedItem="{Binding TimeMarker,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}" 175.                                          telerik:StyleManager.Theme="{StaticResource Theme}"> 176.                    <telerikInput:RadComboBox.ItemTemplate> 177.                        <DataTemplate> 178.                            <StackPanel Orientation="Horizontal"> 179.                                <Rectangle Fill="{Binding TimeMarkerBrush}" 180.                                           Margin="2" 181.                                           Width="12" 182.                                           Height="12" /> 183.                                <TextBlock Text="{Binding TimeMarkerName}" 184.                                           Margin="2" /> 185.                            </StackPanel> 186.                        </DataTemplate> 187.                    </telerikInput:RadComboBox.ItemTemplate> 188.                </telerikInput:RadComboBox> 189.                <telerik:RadToggleButton x:Name="High" 190.                                         BorderThickness="0" 191.                                         Background="{StaticResource RadToolBar_InnerBackground}" 192.                                         DataContext="{TemplateBinding EditedAppointment}" 193.                                         telerik:StyleManager.Theme="{StaticResource Theme}" 194.                                         IsChecked="{Binding Importance,Mode=TwoWay, Converter={StaticResource ImportanceToBooleanConverter},ConverterParameter=High}" 195.                                         Margin="2,2,0,2" 196.                                         Width="23" 197.                                         Height="23" 198.                                         HorizontalContentAlignment="Center" 199.                                         ToolTipService.ToolTip="High importance" 200.                                         CommandParameter="High" 201.                                         Command="telerikScheduler:RadSchedulerCommands.SetAppointmentImportance"> 202.                    <StackPanel HorizontalAlignment="Center"> 203.                        <Path Stretch="Fill" 204.                              Height="10" 205.                              HorizontalAlignment="Center" 206.                              VerticalAlignment="Top" 207.                              Width="5.451" 208.                              Data="M200.39647,58.840393 C200.39337,58.336426 201.14566,57.683922 202.56244,57.684292 C204.06589,57.684685 204.73764,58.357765 204.72783,58.992363 C205.04649,61.795574 203.04713,64.181099 202.47388,66.133446 C201.93753,64.154961 199.9471,61.560352 200.39647,58.840393 z"> 209.                            <Path.Fill> 210.                                <LinearGradientBrush EndPoint="1.059,0.375" 211.                                                     StartPoint="-0.457,0.519"> 212.                                    <GradientStop Color="#FFFF0606" 213.                                                  Offset="0.609" /> 214.                                    <GradientStop Color="#FFBF0303" 215.                                                  Offset="0.927" /> 216.                                </LinearGradientBrush> 217.                            </Path.Fill> 218.                        </Path> 219.                        <Ellipse Height="3" 220.                                 HorizontalAlignment="Center" 221.                                 Margin="0,-1,0,0" 222.                                 VerticalAlignment="Top" 223.                                 Width="3"> 224.                            <Ellipse.Fill> 225.                                <RadialGradientBrush> 226.                                    <GradientStop Color="#FFFF0606" 227.                                                  Offset="0" /> 228.                                    <GradientStop Color="#FFBF0303" 229.                                                  Offset="1" /> 230.                                </RadialGradientBrush> 231.                            </Ellipse.Fill> 232.                        </Ellipse> 233.                    </StackPanel> 234.                </telerik:RadToggleButton> 235.                <telerik:RadToggleButton x:Name="Low" 236.                                         HorizontalContentAlignment="Center" 237.                                         BorderThickness="0" 238.                                         Background="{StaticResource RadToolBar_InnerBackground}" 239.                                         DataContext="{TemplateBinding EditedAppointment}" 240.                                         IsChecked="{Binding Importance,Mode=TwoWay, Converter={StaticResource ImportanceToBooleanConverter},ConverterParameter=Low}" 241.                                         Margin="0,2,0,2" 242.                                         Width="23" 243.                                         Height="23" 244.                                         ToolTipService.ToolTip="Low importance" 245.                                         CommandParameter="Low" 246.                                         telerik:StyleManager.Theme="{StaticResource Theme}" 247.                                         Command="telerikScheduler:RadSchedulerCommands.SetAppointmentImportance"> 248.                    <Path Stretch="Fill" 249.                          Height="12" 250.                          HorizontalAlignment="Center" 251.                          VerticalAlignment="Top" 252.                          Width="9" 253.                          Data="M222.40353,60.139881 L226.65768,60.139843 L226.63687,67.240196 L229.15347,67.240196 L224.37816,71.394943 L219.65274,67.240196 L222.37572,67.219345 z" 254.                          Stroke="#FF0365A7"> 255.                        <Path.Fill> 256.                            <LinearGradientBrush EndPoint="1.059,0.375" 257.                                                 StartPoint="-0.457,0.519"> 258.                                <GradientStop Color="#FFBBE4FF" /> 259.                                <GradientStop Color="#FF024572" 260.                                              Offset="0.836" /> 261.                                <GradientStop Color="#FF43ADF4" 262.                                              Offset="0.466" /> 263.                            </LinearGradientBrush> 264.                        </Path.Fill> 265.                    </Path> 266.                </telerik:RadToggleButton> 267.            </StackPanel > 268.            <Border DataContext="{TemplateBinding EditedAppointment}" 269.                    Background="{Binding Category.CategoryBrush}" 270.                    Visibility="{Binding Category,Converter={StaticResource NullToVisibilityConverter}}" 271.                    CornerRadius="3" 272.                    Height="20" 273.                    Margin="5,10,5,0"> 274.                <TextBlock Text="{Binding Category.DisplayName}" 275.                           VerticalAlignment="Center" 276.                           Margin="5,0,0,0" /> 277.            </Border> 278.            <Grid VerticalAlignment="Stretch" 279.                  HorizontalAlignment="Stretch" 280.                  DataContext="{TemplateBinding EditedAppointment}" 281.                  Background="{TemplateBinding Background}"> 282.                <Grid.RowDefinitions> 283.                    <RowDefinition Height="Auto" /> 284.                    <RowDefinition Height="Auto" /> 285.                    <RowDefinition Height="Auto" /> 286.                    <RowDefinition Height="Auto" /> 287.                    <RowDefinition Height="Auto" /> 288.                    <RowDefinition Height="Auto" /> 289.                    <RowDefinition Height="Auto" /> 290.                    <RowDefinition Height="Auto" /> 291.                    <RowDefinition Height="Auto" /> 292.                    <RowDefinition Height="Auto" /> 293.                </Grid.RowDefinitions> 294.                <Grid.ColumnDefinitions> 295.                    <ColumnDefinition Width="Auto" 296.                                      MinWidth="100" /> 297.                    <ColumnDefinition Width="Auto" 298.                                      MinWidth="200" /> 299.                </Grid.ColumnDefinitions> 300.                <!-- Subject --> 301.                <TextBlock x:Name="SubjectLabel" 302.                           Grid.Row="0" 303.                           Grid.Column="0" 304.                           Margin="0,15,0,2" 305.                           telerik:LocalizationManager.ResourceKey="Subject" 306.                           Style="{StaticResource FormElementTextBlockStyle}" /> 307.                <TextBox x:Name="Subject" 308.                         Grid.Row="0" 309.                         Grid.Column="1" 310.                         MinHeight="22" 311.                         Padding="4 2" 312.                         Width="340" 313.                         HorizontalAlignment="Left" 314.                         Text="{Binding Subject, Mode=TwoWay}" 315.                         MaxLength="255" 316.                         telerik:StyleManager.Theme="{StaticResource Theme}" 317.                         Margin="10,12,20,2" /> 318.                <!-- Description --> 319.                <TextBlock x:Name="DescriptionLabel" 320.                           Grid.Row="1" 321.                           Grid.Column="0" 322.                           Margin="0,13,0,2" 323.                           telerik:LocalizationManager.ResourceKey="Body" 324.                           Style="{StaticResource FormElementTextBlockStyle}" /> 325.                <TextBox x:Name="Body" 326.                         VerticalAlignment="top" 327.                         Grid.Row="1" 328.                         Grid.Column="1" 329.                         Height="Auto" 330.                         MaxHeight="82" 331.                         Width="340" 332.                         HorizontalAlignment="Left" 333.                         MinHeight="22" 334.                         Padding="4 2" 335.                         TextWrapping="Wrap" 336.                         telerik:StyleManager.Theme="{StaticResource Theme}" 337.                         Text="{Binding Body, Mode=TwoWay}" 338.                         AcceptsReturn="true" 339.                         Margin="10,10,20,2" 340.                         HorizontalScrollBarVisibility="Auto" 341.                         VerticalScrollBarVisibility="Auto" /> 342.                <!-- Start/End date --> 343.                <TextBlock x:Name="StartDateLabel" 344.                           Grid.Row="2" 345.                           Grid.Column="0" 346.                           Margin="0,13,0,2" 347.                           telerik:LocalizationManager.ResourceKey="StartTime" 348.                           Style="{StaticResource FormElementTextBlockStyle}" /> 349.                <telerikScheduler:DateTimePicker x:Name="StartDateTime" 350.                                                 Height="22" 351.                                                 Grid.Row="2" 352.                                                 Grid.Column="1" 353.                                                 HorizontalAlignment="Left" 354.                                                 Margin="10,10,20,2" 355.                                                 Style="{StaticResource FormElementStyle}" 356.                                                 SelectedDateTime="{Binding Start, Mode=TwoWay}" 357.                                                 telerikScheduler:StartEndDatePicker.EndPicker="{Binding ElementName=EndDateTime}" 358.                                                 IsTabStop="False" 359.                                                 IsEnabled="False" /> 360.                <TextBlock x:Name="EndDateLabel" 361.                           Grid.Row="3" 362.                           Grid.Column="0" 363.                           Margin="0,13,0,2" 364.                           telerik:LocalizationManager.ResourceKey="EndTime" 365.                           Style="{StaticResource FormElementTextBlockStyle}" /> 366.                <telerikScheduler:DateTimePicker x:Name="EndDateTime" 367.                                                 Height="22" 368.                                                 Grid.Row="3" 369.                                                 Grid.Column="1" 370.                                                 HorizontalAlignment="Left" 371.                                                 Margin="10,10,20,2" 372.                                                 Style="{StaticResource FormElementStyle}" 373.                                                 IsTabStop="False" 374.                                                 IsEnabled="False" 375.                                                 SelectedDateTime="{Binding End, Mode=TwoWay}" /> 376.                <!-- Is-all-day selector --> 377.                <CheckBox x:Name="AllDayEventCheckbox" 378.                          IsChecked="{Binding IsAllDayEvent, Mode=TwoWay}" 379.                          Grid.Row="4" 380.                          Grid.Column="1" 381.                          Margin="10,10,20,2" 382.                          HorizontalAlignment="Left" 383.                          telerik:StyleManager.Theme="{StaticResource Theme}" 384.                          telerik:LocalizationManager.ResourceKey="AllDayEvent"> 385.                    <telerik:CommandManager.InputBindings> 386.                        <telerik:InputBindingCollection> 387.                            <telerik:MouseBinding Command="telerikScheduler:RadSchedulerCommands.ChangeTimePickersVisibility" 388.                                                  Gesture="LeftClick" /> 389.                        </telerik:InputBindingCollection> 390.                    </telerik:CommandManager.InputBindings> 391.                </CheckBox> 392.                <Grid Grid.Row="5" 393.                      Grid.ColumnSpan="2"> 394.                    <Grid.ColumnDefinitions> 395.                        <ColumnDefinition Width="Auto" 396.                                          MinWidth="100" /> 397.                        <ColumnDefinition Width="Auto" 398.                                          MinWidth="200" /> 399.                    </Grid.ColumnDefinitions> 400.                    <Grid.RowDefinitions> 401.                        <RowDefinition Height="Auto" /> 402.                        <RowDefinition Height="Auto" /> 403.                    </Grid.RowDefinitions> 404.                    <TextBlock Text="Applicant" 405.                               Margin="0,13,0,2" 406.                               Style="{StaticResource FormElementTextBlockStyle}" /> 407.                    <telerikInput:RadComboBox IsEditable="False" 408.                                              Grid.Column="1" 409.                                              Height="24" 410.                                              VerticalAlignment="Center" 411.                                              ItemsSource="{Binding Source={StaticResource DataContextProxy}, Path=DataSource.ApplicantList}" 412.                                              SelectedValue="{Binding ApplicantID, Mode=TwoWay}" 413.                                              SelectedValuePath="ApplicantID" 414.                                              DisplayMemberPath="FirstName" /> 415.                       416.                    <TextBlock Text="Job" 417.                               Margin="0,13,0,2" 418.                               Grid.Row="1" 419.                               Style="{StaticResource FormElementTextBlockStyle}" /> 420.                    <telerikInput:RadComboBox IsEditable="False" 421.                                              Grid.Column="1" 422.                                              Grid.Row="1" 423.                                              Height="24" 424.                                              VerticalAlignment="Center" 425.                                              ItemsSource="{Binding Source={StaticResource DataContextProxy}, Path=DataSource.JobsList}" 426.                                              SelectedValue="{Binding PostingID, Mode=TwoWay}" 427.                                              SelectedValuePath="PostingID" 428.                                              DisplayMemberPath="JobTitle"/> 429.                </Grid> 430.                    <!-- Resources --> 431.                <Grid x:Name="ResourcesLayout" 432.                      Grid.Row="7" 433.                      Grid.Column="0" 434.                      Grid.ColumnSpan="2" 435.                      MaxHeight="130" 436.                      Margin="20,5,20,0"> 437.                    <Border Margin="0" 438.                            BorderThickness="1" 439.                            BorderBrush="{StaticResource GenericShallowBorderBrush}" 440.                            Visibility="{Binding ElementName=ResourcesScrollViewer, Path=ComputedVerticalScrollBarVisibility}"></Border> 441.                    <ScrollViewer x:Name="ResourcesScrollViewer" 442.                                  IsTabStop="false" 443.                                  Grid.Row="6" 444.                                  Grid.Column="0" 445.                                  Grid.ColumnSpan="2" 446.                                  Margin="1" 447.                                  telerik:StyleManager.Theme="{StaticResource Theme}" 448.                                  VerticalScrollBarVisibility="Auto"> 449.                        <scheduler:ResourcesItemsControl x:Name="PART_Resources" 450.                                                         HorizontalAlignment="Left" 451.                                                         Padding="0,2,0,5" 452.                                                         IsTabStop="false" 453.                                                         ItemsSource="{TemplateBinding ResourceTypeModels}" 454.                                                         ItemTemplateSelector="{StaticResource ItemTemplateSelector}" /> 455.                    </ScrollViewer> 456.                </Grid> 457.                <StackPanel x:Name="FooterControls" 458.                            Margin="5 10 10 10" 459.                            Grid.Row="8" 460.                            Grid.Column="1" 461.                            HorizontalAlignment="Left" 462.                            Orientation="Horizontal"> 463.                    <telerik:RadButton x:Name="OKButton" 464.                                       Margin="5" 465.                                       Padding="10 0" 466.                                       MinWidth="80" 467.                                       Command="telerikScheduler:RadSchedulerCommands.SaveAppointment" 468.                                       telerik:StyleManager.Theme="{StaticResource Theme}" 469.                                       telerikNavigation:RadWindow.ResponseButton="Accept" 470.                                       telerik:LocalizationManager.ResourceKey="SaveAndCloseCommandText"> 471.                    </telerik:RadButton> 472.                    <telerik:RadButton x:Name="CancelButton" 473.                                       Margin="5" 474.                                       Padding="10 0" 475.                                       MinWidth="80" 476.                                       telerik:LocalizationManager.ResourceKey="Cancel" 477.                                       telerik:StyleManager.Theme="{StaticResource Theme}" 478.                                       telerikNavigation:RadWindow.ResponseButton="Cancel" 479.                                       Command="telerik:WindowCommands.Close"> 480.                    </telerik:RadButton> 481.                </StackPanel> 482.            </Grid> 483.            <vsm:VisualStateManager.VisualStateGroups> 484.                <vsm:VisualStateGroup x:Name="RecurrenceRuleState"> 485.                    <vsm:VisualState x:Name="RecurrenceRuleIsNull"> 486.                        <Storyboard> 487.                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="StartDateTime" 488.                                                           Storyboard.TargetProperty="IsEnabled" 489.                                                           Duration="0"> 490.                                <DiscreteObjectKeyFrame KeyTime="0" 491.                                                        Value="True" /> 492.                            </ObjectAnimationUsingKeyFrames> 493.                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="EndDateTime" 494.                                                           Storyboard.TargetProperty="IsEnabled" 495.                                                           Duration="0"> 496.                                <DiscreteObjectKeyFrame KeyTime="0" 497.                                                        Value="True" /> 498.                            </ObjectAnimationUsingKeyFrames> 499.                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="AllDayEventCheckbox" 500.                                                           Storyboard.TargetProperty="IsEnabled" 501.                                                           Duration="0"> 502.                                <DiscreteObjectKeyFrame KeyTime="0" 503.                                                        Value="True" /> 504.                            </ObjectAnimationUsingKeyFrames> 505.                        </Storyboard> 506.                    </vsm:VisualState> 507.                    <vsm:VisualState x:Name="RecurrenceRuleIsNotNull"> 508.                        <Storyboard> 509.                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="StartDateTime" 510.                                                           Storyboard.TargetProperty="IsEnabled" 511.                                                           Duration="0"> 512.                                <DiscreteObjectKeyFrame KeyTime="0" 513.                                                        Value="False" /> 514.                            </ObjectAnimationUsingKeyFrames> 515.                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="EndDateTime" 516.                                                           Storyboard.TargetProperty="IsEnabled" 517.                                                           Duration="0"> 518.                                <DiscreteObjectKeyFrame KeyTime="0" 519.                                                        Value="False" /> 520.                            </ObjectAnimationUsingKeyFrames> 521.                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="AllDayEventCheckbox" 522.                                                           Storyboard.TargetProperty="IsEnabled" 523.                                                           Duration="0"> 524.                                <DiscreteObjectKeyFrame KeyTime="0" 525.                                                        Value="False" /> 526.                            </ObjectAnimationUsingKeyFrames> 527.                        </Storyboard> 528.                    </vsm:VisualState> 529.                </vsm:VisualStateGroup> 530.            </vsm:VisualStateManager.VisualStateGroups> 531.        </StackPanel> 532.    </ControlTemplate> 533.    <DataTemplate x:Key="AppointmentDialogWindowHeaderDataTemplate"> 534.        <StackPanel Orientation="Horizontal" 535.                    MaxWidth="400"> 536.            <TextBlock telerik:LocalizationManager.ResourceKey="Event" 537.                       Visibility="{Binding Appointment.IsAllDayEvent, Converter={StaticResource BooleanToVisibilityConverter}}" /> 538.            <TextBlock telerik:LocalizationManager.ResourceKey="Appointment" 539.                       Visibility="{Binding Appointment.IsAllDayEvent, Converter={StaticResource InvertedBooleanToVisibilityConverter}}" /> 540.            <TextBlock Text=" - " /> 541.            <TextBlock x:Name="SubjectTextBlock" 542.                       Visibility="{Binding Appointment.Subject, Converter={StaticResource NullToVisibilityConverter}}" 543.                       Text="{Binding Appointment.Subject}" /> 544.            <TextBlock telerik:LocalizationManager.ResourceKey="Untitled" 545.                       Visibility="{Binding Appointment.Subject, Converter={StaticResource InvertedNullToVisibilityConverter}}" /> 546.        </StackPanel> 547.    </DataTemplate> 548.    <Style x:Key="EditAppointmentStyle" 549.           TargetType="telerikScheduler:AppointmentDialogWindow"> 550.        <Setter Property="IconTemplate" 551.                Value="{StaticResource IconDataEditTemplate}" /> 552.        <Setter Property="HeaderTemplate" 553.                Value="{StaticResource AppointmentDialogWindowHeaderDataTemplate}" /> 554.        <Setter Property="Background" 555.                Value="{StaticResource DialogWindowBackground}" /> 556.        <Setter Property="Template" 557.                Value="{StaticResource EditAppointmentTemplate}" /> 558.    </Style> 559.</UserControl.Resources> The first line there is the DataContextProxy I mentioned previously- we use that again to work a bit of magic in this template. Where we start getting into the dialog in question is line 132, but line 407 is where things start getting interesting.  The ItemsSource is pointing at a list that exists in my ViewModel (or code-behind, if it is used as a DataContext), the SelectedValue is the item I am actually binding from the applicant (note the TwoWay binding), and SelectedValuePath and DisplayMemberPath ensure the proper applicant is being displayed from the collection.  You will also see similar starting on line 420 where I do the same for the Jobs we'll be displaying. Just to wrap-up the Xaml, here's the RadScheduler declaraction that ties this all together and will be the main focus of our view: 01.<telerikScheduler:RadScheduler x:Name="xJobsScheduler" 02.                  Grid.Row="1" 03.                  Grid.Column="1" 04.                  Width="800" 05.                  MinWidth="600" 06.                  Height="500" 07.                  MinHeight="300" 08.                  AppointmentsSource="{Binding Interviews}" 09.                  EditAppointmentStyle="{StaticResource EditAppointmentStyle}" 10.                  command:AppointmentAddedEventClass.Command="{Binding AddAppointmentCommand}" 11.                  command:ApptCreatedEventClass.Command="{Binding ApptCreatingCommand}" 12.                  command:ApptEditedEventClass.Command="{Binding ApptEditedCommand}" 13.                  command:ApptDeletedEventClass.Command="{Binding ApptDeletedCommand}"> 14.</telerikScheduler:RadScheduler> Now, we get to the ViewModel and what it takes to get that rigged up.  And for those of you who remember the jobs post, those command:s in the Xaml are pointing to attached behavior commands that reproduce the respective events.  This becomes very handy when we're setting up the code-behind version. ;) ViewModel I've been liking this approach so far, so I'm going to put the entire ViewModel here and then go into the lines of interest.  Of course, feel free to ask me questions about anything that isn't clear (by line number, ideally) so I can help out if I have missed anything important: 001.public class SchedulerViewModel : ViewModelBase 002.{ 003.    private readonly IEventAggregator eventAggregator; 004.    private readonly IRegionManager regionManager; 005.   006.    public RecruitingContext context; 007.   008.    private ObservableItemCollection<InterviewAppointment> _interviews = new ObservableItemCollection<InterviewAppointment>(); 009.    public ObservableItemCollection<InterviewAppointment> Interviews 010.    { 011.        get { return _interviews; } 012.        set 013.        { 014.            if (_interviews != value) 015.            { 016.                _interviews = value; 017.                NotifyChanged("Interviews"); 018.            } 019.        } 020.    } 021.   022.    private QueryableCollectionView _jobsList; 023.    public QueryableCollectionView JobsList 024.    { 025.        get { return this._jobsList; } 026.        set 027.        { 028.            if (this._jobsList != value) 029.            { 030.                this._jobsList = value; 031.                this.NotifyChanged("JobsList"); 032.            } 033.        } 034.    } 035.   036.    private QueryableCollectionView _applicantList; 037.    public QueryableCollectionView ApplicantList 038.    { 039.        get { return _applicantList; } 040.        set 041.        { 042.            if (_applicantList != value) 043.            { 044.                _applicantList = value; 045.                NotifyChanged("ApplicantList"); 046.            } 047.        } 048.    } 049.   050.    public DelegateCommand<object> AddAppointmentCommand { get; set; } 051.    public DelegateCommand<object> ApptCreatingCommand { get; set; } 052.    public DelegateCommand<object> ApptEditedCommand { get; set; } 053.    public DelegateCommand<object> ApptDeletedCommand { get; set; } 054.   055.    public SchedulerViewModel(IEventAggregator eventAgg, IRegionManager regionmanager) 056.    { 057.        // set Unity items 058.        this.eventAggregator = eventAgg; 059.        this.regionManager = regionmanager; 060.   061.        // load our context 062.        context = new RecruitingContext(); 063.        LoadOperation<Interview> loadOp = context.Load(context.GetInterviewsQuery()); 064.        loadOp.Completed += new EventHandler(loadOp_Completed); 065.   066.        this._jobsList = new QueryableCollectionView(context.JobPostings); 067.        context.Load(context.GetJobPostingsQuery()); 068.   069.        this._applicantList = new QueryableCollectionView(context.Applicants); 070.        context.Load(context.GetApplicantsQuery()); 071.   072.        AddAppointmentCommand = new DelegateCommand<object>(this.AddAppt); 073.        ApptCreatingCommand = new DelegateCommand<object>(this.ApptCreating); 074.        ApptEditedCommand = new DelegateCommand<object>(this.ApptEdited); 075.        ApptDeletedCommand = new DelegateCommand<object>(this.ApptDeleted); 076.   077.    } 078.   079.    void loadOp_Completed(object sender, EventArgs e) 080.    { 081.        LoadOperation loadop = sender as LoadOperation; 082.   083.        foreach (var ent in loadop.Entities) 084.        { 085.            _interviews.Add(EntityToAppointment(ent as Interview)); 086.        } 087.    } 088.   089.    #region Appointment Adding 090.   091.    public void AddAppt(object obj) 092.    { 093.        // now we have a new InterviewAppointment to add to our QCV :) 094.        InterviewAppointment newInterview = obj as InterviewAppointment; 095.   096.        this.context.Interviews.Add(AppointmentToEntity(newInterview)); 097.        this.context.SubmitChanges((s) => 098.        { 099.            ActionHistory myAction = new ActionHistory(); 100.            myAction.InterviewID = newInterview.InterviewID; 101.            myAction.PostingID = newInterview.PostingID; 102.            myAction.ApplicantID = newInterview.ApplicantID; 103.            myAction.Description = String.Format("Interview with {0} has been created by {1}", newInterview.ApplicantID.ToString(), "default user"); 104.            myAction.TimeStamp = DateTime.Now; 105.            eventAggregator.GetEvent<AddActionEvent>().Publish(myAction); 106.        } 107.            , null); 108.    } 109.   110.    public void ApptCreating(object obj) 111.    { 112.        // handled in the behavior, just a placeholder to ensure it runs :) 113.    } 114.   115.    #endregion 116.   117.    #region Appointment Editing 118.   119.    public void ApptEdited(object obj) 120.    { 121.        Interview editedInterview = (from x in context.Interviews 122.                            where x.InterviewID == (obj as InterviewAppointment).InterviewID 123.                            select x).SingleOrDefault(); 124.   125.        CopyAppointmentEdit(editedInterview, obj as InterviewAppointment); 126.   127.        context.SubmitChanges((s) => { 128.            ActionHistory myAction = new ActionHistory(); 129.            myAction.InterviewID = editedInterview.InterviewID; 130.            myAction.PostingID = editedInterview.PostingID; 131.            myAction.ApplicantID = editedInterview.ApplicantID; 132.            myAction.Description = String.Format("Interview with {0} has been modified by {1}", editedInterview.ApplicantID.ToString(), "default user"); 133.            myAction.TimeStamp = DateTime.Now; 134.            eventAggregator.GetEvent<AddActionEvent>().Publish(myAction); } 135.            , null); 136.    } 137.   138.    #endregion 139.   140.    #region Appointment Deleting 141.   142.    public void ApptDeleted(object obj) 143.    { 144.        Interview deletedInterview = (from x in context.Interviews 145.                                      where x.InterviewID == (obj as InterviewAppointment).InterviewID 146.                                      select x).SingleOrDefault(); 147.   148.        context.Interviews.Remove(deletedInterview); 149.        context.SubmitChanges((s) => 150.        { 151.            ActionHistory myAction = new ActionHistory(); 152.            myAction.InterviewID = deletedInterview.InterviewID; 153.            myAction.PostingID = deletedInterview.PostingID; 154.            myAction.ApplicantID = deletedInterview.ApplicantID; 155.            myAction.Description = String.Format("Interview with {0} has been deleted by {1}", deletedInterview.ApplicantID.ToString(), "default user"); 156.            myAction.TimeStamp = DateTime.Now; 157.            eventAggregator.GetEvent<AddActionEvent>().Publish(myAction); 158.        } 159.            , null); 160.    } 161.   162.    #endregion 163.   164.    #region Appointment Helpers :) 165.   166.    public Interview AppointmentToEntity(InterviewAppointment ia) 167.    { 168.        Interview newInterview = new Interview(); 169.        newInterview.Subject = ia.Subject; 170.        newInterview.Body = ia.Body; 171.        newInterview.Start = ia.Start; 172.        newInterview.End = ia.End; 173.        newInterview.ApplicantID = ia.ApplicantID; 174.        newInterview.PostingID = ia.PostingID; 175.        newInterview.InterviewID = ia.InterviewID; 176.   177.        return newInterview; 178.    } 179.   180.    public InterviewAppointment EntityToAppointment(Interview ia) 181.    { 182.        InterviewAppointment newInterview = new InterviewAppointment(); 183.        newInterview.Subject = ia.Subject; 184.        newInterview.Body = ia.Body; 185.        newInterview.Start = ia.Start; 186.        newInterview.End = ia.End; 187.        newInterview.ApplicantID = ia.ApplicantID; 188.        newInterview.PostingID = ia.PostingID; 189.        newInterview.InterviewID = ia.InterviewID; 190.   191.        return newInterview; 192.    } 193.   194.    public void CopyAppointmentEdit(Interview entityInterview, InterviewAppointment appointmentInterview) 195.    { 196.        entityInterview.Subject = appointmentInterview.Subject; 197.        entityInterview.Body = appointmentInterview.Body; 198.        entityInterview.Start = appointmentInterview.Start; 199.        entityInterview.End = appointmentInterview.End; 200.        entityInterview.ApplicantID = appointmentInterview.ApplicantID; 201.        entityInterview.PostingID = appointmentInterview.PostingID; 202.    } 203.   204.    #endregion 205.} One thing we're doing here which you won't see in any of the other ViewModels is creating a duplicate collection.  I know this is something which will be fixed down the line for using RadScheduler, simplifying this process, but with WCF RIA changing as it does I wanted to ensure functionality would remain consistent as I continued development on this application.  So, I do a little bit of duplication, but for the greater good.  This all takes place starting on line 79, so for every entity that comes back we add it to the collection that is bound to RadScheduler.  Otherwise, the DelegateCommands that you see correspond directly to the events they are named after.  In each case, rather than sending over the full event arguments, I just send in the appointment in question (coming through as the object obj in all cases) so I can add (line 91), edit (line 119), and delete appointments (line 142) like normal.  This just ensures they get updated back to my database.  Also, the one bit of code you won't see is for the Appointment Creating (line 110) event- that is because in the command I've created I simply make the replacement I need to: 1.void element_AppointmentCreating(object sender, AppointmentCreatingEventArgs e) 2.{ 3.    e.NewAppointment = new InterviewAppointment(); 4.    base.ExecuteCommand(); 5.} And the ViewModel is none the wiser, the appointments just work as far as it is concerned since as they are created they become InterviewAppointments.  End result?  I've customized my EditAppointmentDialog as follows: And adding, editing, and deleting appointments works like a charm.  I can even 'edit' by moving appointments around RadScheduler, so as they are dropped into a timeslot they perform their full edit routine and things get updated. And then, the Code-Behind Version Perhaps the thing I like the most about doing one then the other is I get to steal 90% or more of the code from the MVVM version.  For example, the only real changes to the Code-Behind Xaml file exist in the control declaration, in which I use events instead of attached-behavior-event-commands: 01.<telerikScheduler:RadScheduler x:Name="xJobsScheduler" 02.                  Grid.Row="1" 03.                  Grid.Column="1" 04.                  Width="800" 05.                  MinWidth="600" 06.                  Height="500" 07.                  MinHeight="300" 08.                  EditAppointmentStyle="{StaticResource EditAppointmentStyle}" 09.                  AppointmentAdded="xJobsScheduler_AppointmentAdded" 10.                  AppointmentCreating="xJobsScheduler_AppointmentCreating" 11.                  AppointmentEdited="xJobsScheduler_AppointmentEdited" 12.                  AppointmentDeleted="xJobsScheduler_AppointmentDeleted"> 13.</telerikScheduler:RadScheduler> Easy, right?  Otherwise, all the same styling in UserControl.Resources was re-used, right down to the DataContextProxy that lets us bind to a collection from our viewmodel (in this case, our code-behind) to use within the DataTemplate.  The code conversion gets even easier, as I could literally copy and paste almost everything from the ViewModel to my Code-Behind, just a matter of pasting the right section into the right event.  Here's the code-behind as proof: 001.public partial class SchedulingView : UserControl, INotifyPropertyChanged 002.{ 003.    public RecruitingContext context; 004.   005.    private QueryableCollectionView _jobsList; 006.    public QueryableCollectionView JobsList 007.    { 008.        get { return this._jobsList; } 009.        set 010.        { 011.            if (this._jobsList != value) 012.            { 013.                this._jobsList = value; 014.                this.NotifyChanged("JobsList"); 015.            } 016.        } 017.    } 018.   019.    private QueryableCollectionView _applicantList; 020.    public QueryableCollectionView ApplicantList 021.    { 022.        get { return _applicantList; } 023.        set 024.        { 025.            if (_applicantList != value) 026.            { 027.                _applicantList = value; 028.                NotifyChanged("ApplicantList"); 029.            } 030.        } 031.    } 032.   033.    private ObservableItemCollection<InterviewAppointment> _interviews = new ObservableItemCollection<InterviewAppointment>(); 034.    public ObservableItemCollection<InterviewAppointment> Interviews 035.    { 036.        get { return _interviews; } 037.        set 038.        { 039.            if (_interviews != value) 040.            { 041.                _interviews = value; 042.                NotifyChanged("Interviews"); 043.            } 044.        } 045.    } 046.   047.    public SchedulingView() 048.    { 049.        InitializeComponent(); 050.   051.        this.DataContext = this; 052.   053.        this.Loaded += new RoutedEventHandler(SchedulingView_Loaded); 054.    } 055.   056.    void SchedulingView_Loaded(object sender, RoutedEventArgs e) 057.    { 058.        this.xJobsScheduler.AppointmentsSource = Interviews; 059.   060.        context = new RecruitingContext(); 061.           062.        LoadOperation loadop = context.Load(context.GetInterviewsQuery()); 063.        loadop.Completed += new EventHandler(loadop_Completed); 064.   065.        this._applicantList = new QueryableCollectionView(context.Applicants); 066.        context.Load(context.GetApplicantsQuery()); 067.   068.        this._jobsList = new QueryableCollectionView(context.JobPostings); 069.        context.Load(context.GetJobPostingsQuery()); 070.    } 071.   072.    void loadop_Completed(object sender, EventArgs e) 073.    { 074.        LoadOperation loadop = sender as LoadOperation; 075.   076.        _interviews.Clear(); 077.   078.        foreach (var ent in loadop.Entities) 079.        { 080.            _interviews.Add(EntityToAppointment(ent as Interview)); 081.        } 082.    } 083.   084.    private void xJobsScheduler_AppointmentAdded(object sender, Telerik.Windows.Controls.AppointmentAddedEventArgs e) 085.    { 086.        // now we have a new InterviewAppointment to add to our QCV :) 087.        InterviewAppointment newInterview = e.Appointment as InterviewAppointment; 088.   089.        this.context.Interviews.Add(AppointmentToEntity(newInterview)); 090.        this.context.SubmitChanges((s) => 091.        { 092.            ActionHistory myAction = new ActionHistory(); 093.            myAction.InterviewID = newInterview.InterviewID; 094.            myAction.PostingID = newInterview.PostingID; 095.            myAction.ApplicantID = newInterview.ApplicantID; 096.            myAction.Description = String.Format("Interview with {0} has been created by {1}", newInterview.ApplicantID.ToString(), "default user"); 097.            myAction.TimeStamp = DateTime.Now; 098.            context.ActionHistories.Add(myAction); 099.            context.SubmitChanges(); 100.        } 101.            , null); 102.    } 103.   104.    private void xJobsScheduler_AppointmentCreating(object sender, Telerik.Windows.Controls.AppointmentCreatingEventArgs e) 105.    { 106.        e.NewAppointment = new InterviewAppointment(); 107.    } 108.   109.    private void xJobsScheduler_AppointmentEdited(object sender, Telerik.Windows.Controls.AppointmentEditedEventArgs e) 110.    { 111.        Interview editedInterview = (from x in context.Interviews 112.                                     where x.InterviewID == (e.Appointment as InterviewAppointment).InterviewID 113.                                     select x).SingleOrDefault(); 114.   115.        CopyAppointmentEdit(editedInterview, e.Appointment as InterviewAppointment); 116.   117.        context.SubmitChanges((s) => 118.        { 119.            ActionHistory myAction = new ActionHistory(); 120.            myAction.InterviewID = editedInterview.InterviewID; 121.            myAction.PostingID = editedInterview.PostingID; 122.            myAction.ApplicantID = editedInterview.ApplicantID; 123.            myAction.Description = String.Format("Interview with {0} has been modified by {1}", editedInterview.ApplicantID.ToString(), "default user"); 124.            myAction.TimeStamp = DateTime.Now; 125.            context.ActionHistories.Add(myAction); 126.            context.SubmitChanges(); 127.        } 128.            , null); 129.    } 130.   131.    private void xJobsScheduler_AppointmentDeleted(object sender, Telerik.Windows.Controls.AppointmentDeletedEventArgs e) 132.    { 133.        Interview deletedInterview = (from x in context.Interviews 134.                                      where x.InterviewID == (e.Appointment as InterviewAppointment).InterviewID 135.                                      select x).SingleOrDefault(); 136.   137.        context.Interviews.Remove(deletedInterview); 138.        context.SubmitChanges((s) => 139.        { 140.            ActionHistory myAction = new ActionHistory(); 141.            myAction.InterviewID = deletedInterview.InterviewID; 142.            myAction.PostingID = deletedInterview.PostingID; 143.            myAction.ApplicantID = deletedInterview.ApplicantID; 144.            myAction.Description = String.Format("Interview with {0} has been deleted by {1}", deletedInterview.ApplicantID.ToString(), "default user"); 145.            myAction.TimeStamp = DateTime.Now; 146.            context.ActionHistories.Add(myAction); 147.            context.SubmitChanges(); 148.        } 149.            , null); 150.    } 151.   152.    #region Appointment Helpers :) 153.   154.    public Interview AppointmentToEntity(InterviewAppointment ia) 155.    { 156.        Interview newInterview = new Interview(); 157.        newInterview.Subject = ia.Subject; 158.        newInterview.Body = ia.Body; 159.        newInterview.Start = ia.Start; 160.        newInterview.End = ia.End; 161.        newInterview.ApplicantID = ia.ApplicantID; 162.        newInterview.PostingID = ia.PostingID; 163.        newInterview.InterviewID = ia.InterviewID; 164.   165.        return newInterview; 166.    } 167.   168.    public InterviewAppointment EntityToAppointment(Interview ia) 169.    { 170.        InterviewAppointment newInterview = new InterviewAppointment(); 171.        newInterview.Subject = ia.Subject; 172.        newInterview.Body = ia.Body; 173.        newInterview.Start = ia.Start; 174.        newInterview.End = ia.End; 175.        newInterview.ApplicantID = ia.ApplicantID; 176.        newInterview.PostingID = ia.PostingID; 177.        newInterview.InterviewID = ia.InterviewID; 178.   179.        return newInterview; 180.    } 181.   182.    public void CopyAppointmentEdit(Interview entityInterview, InterviewAppointment appointmentInterview) 183.    { 184.        entityInterview.Subject = appointmentInterview.Subject; 185.        entityInterview.Body = appointmentInterview.Body; 186.        entityInterview.Start = appointmentInterview.Start; 187.        entityInterview.End = appointmentInterview.End; 188.        entityInterview.ApplicantID = appointmentInterview.ApplicantID; 189.        entityInterview.PostingID = appointmentInterview.PostingID; 190.    } 191.   192.    #endregion 193.   194.    #region INotifyPropertyChanged Members 195.   196.    public event PropertyChangedEventHandler PropertyChanged; 197.   198.    public void NotifyChanged(string propertyName) 199.    { 200.        if (string.IsNullOrEmpty(propertyName)) 201.            throw new ArgumentException("propertyName"); 202.   203.        PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 204.    } 205.   206.    #endregion 207.} Nice... right? :) One really important thing to note as well.  See on line 51 where I set the DataContext before the Loaded event?  This is super important, as if you don't have this set before the usercontrol is loaded, the DataContextProxy has no context to use and your EditAppointmentDialog Job/Applicant dropdowns will be blank and empty.  Trust me on this, took a little bit of debugging to figure out that by setting the DataContext post-loaded would only lead to disaster and frustration.  Otherwise, the only other real difference is that instead of sending an ActionHistory item through an event to get added to the database and saved, I do those right in the callback from submitting.  The Result Again, I only have to post one picture because these bad boys used nearly identical code for both the MVVM and the code-behind views, so our end result is... So what have we learned here today?  One, for the most part this MVVM thing is somewhat easy.  Yeah, you sometimes have to write a bunch of extra code, but with the help of a few useful snippits you can turn the process into a pretty streamlined little workflow.  Heck, this story gets even easier as you can see in this blog post by Michael Washington- specifically run a find on 'InvokeCommandAction' and you'll see the section regarding the command on TreeView in Blend 4.  Brilliant!  MVVM never looked so sweet! Otherwise, it is business as usual with RadScheduler for Silverlight whichever path you're choosing for your development.  Between now and the next post, I'll be cleaning up styles a bit (those RadComboBoxes are a little too close to my labels!) and adding some to the RowDetailsViews for Applicants and Jobs, so you can see all the info for an appointment in the dropdown tab view.  Otherwise, we're about ready to call a wrap on this oneDid you know that DotNetSlackers also publishes .net articles written by top known .net Authors? We already have over 80 articles in several categories including Silverlight. Take a look: here.

    Read the article

  • Silverlight Recruiting Application Part 5 - Jobs Module / View

    Now we starting getting into a more code-heavy portion of this series, thankfully though this means the groundwork is all set for the most part and after adding the modules we will have a complete application that can be provided with full source. The Jobs module will have two concerns- adding and maintaining jobs that can then be broadcast out to the website. How they are displayed on the site will be handled by our admin system (which will just poll from this common database), so we aren't too concerned with that, but rather with getting the information into the system and allowing the backend administration/HR users to keep things up to date. Since there is a fair bit of information that we want to display, we're going to move editing to a separate view so we can get all that information in an easy-to-use spot. With all the files created for this module, the project looks something like this: And now... on to the code. XAML for the Job Posting View All we really need for the Job Posting View is a RadGridView and a few buttons. This will let us both show off records and perform operations on the records without much hassle. That XAML is going to look something like this: 01.<Grid x:Name="LayoutRoot" 02.Background="White"> 03.<Grid.RowDefinitions> 04.<RowDefinition Height="30" /> 05.<RowDefinition /> 06.</Grid.RowDefinitions> 07.<StackPanel Orientation="Horizontal"> 08.<Button x:Name="xAddRecordButton" 09.Content="Add Job" 10.Width="120" 11.cal:Click.Command="{Binding AddRecord}" 12.telerik:StyleManager.Theme="Windows7" /> 13.<Button x:Name="xEditRecordButton" 14.Content="Edit Job" 15.Width="120" 16.cal:Click.Command="{Binding EditRecord}" 17.telerik:StyleManager.Theme="Windows7" /> 18.</StackPanel> 19.<telerikGrid:RadGridView x:Name="xJobsGrid" 20.Grid.Row="1" 21.IsReadOnly="True" 22.AutoGenerateColumns="False" 23.ColumnWidth="*" 24.RowDetailsVisibilityMode="VisibleWhenSelected" 25.ItemsSource="{Binding MyJobs}" 26.SelectedItem="{Binding SelectedJob, Mode=TwoWay}" 27.command:SelectedItemChangedEventClass.Command="{Binding SelectedItemChanged}"> 28.<telerikGrid:RadGridView.Columns> 29.<telerikGrid:GridViewDataColumn Header="Job Title" 30.DataMemberBinding="{Binding JobTitle}" 31.UniqueName="JobTitle" /> 32.<telerikGrid:GridViewDataColumn Header="Location" 33.DataMemberBinding="{Binding Location}" 34.UniqueName="Location" /> 35.<telerikGrid:GridViewDataColumn Header="Resume Required" 36.DataMemberBinding="{Binding NeedsResume}" 37.UniqueName="NeedsResume" /> 38.<telerikGrid:GridViewDataColumn Header="CV Required" 39.DataMemberBinding="{Binding NeedsCV}" 40.UniqueName="NeedsCV" /> 41.<telerikGrid:GridViewDataColumn Header="Overview Required" 42.DataMemberBinding="{Binding NeedsOverview}" 43.UniqueName="NeedsOverview" /> 44.<telerikGrid:GridViewDataColumn Header="Active" 45.DataMemberBinding="{Binding IsActive}" 46.UniqueName="IsActive" /> 47.</telerikGrid:RadGridView.Columns> 48.</telerikGrid:RadGridView> 49.</Grid> I'll explain what's happening here by line numbers: Lines 11 and 16: Using the same type of click commands as we saw in the Menu module, we tie the button clicks to delegate commands in the viewmodel. Line 25: The source for the jobs will be a collection in the viewmodel. Line 26: We also bind the selected item to a public property from the viewmodel for use in code. Line 27: We've turned the event into a command so we can handle it via code in the viewmodel. So those first three probably make sense to you as far as Silverlight/WPF binding magic is concerned, but for line 27... This actually comes from something I read onDamien Schenkelman's blog back in the day for creating an attached behavior from any event. So, any time you see me using command:Whatever.Command, the backing for it is actually something like this: SelectedItemChangedEventBehavior.cs: 01.public class SelectedItemChangedEventBehavior : CommandBehaviorBase<Telerik.Windows.Controls.DataControl> 02.{ 03.public SelectedItemChangedEventBehavior(DataControl element) 04.: base(element) 05.{ 06.element.SelectionChanged += new EventHandler<SelectionChangeEventArgs>(element_SelectionChanged); 07.} 08.void element_SelectionChanged(object sender, SelectionChangeEventArgs e) 09.{ 10.// We'll only ever allow single selection, so will only need item index 0 11.base.CommandParameter = e.AddedItems[0]; 12.base.ExecuteCommand(); 13.} 14.} SelectedItemChangedEventClass.cs: 01.public class SelectedItemChangedEventClass 02.{ 03.#region The Command Stuff 04.public static ICommand GetCommand(DependencyObject obj) 05.{ 06.return (ICommand)obj.GetValue(CommandProperty); 07.} 08.public static void SetCommand(DependencyObject obj, ICommand value) 09.{ 10.obj.SetValue(CommandProperty, value); 11.} 12.public static readonly DependencyProperty CommandProperty = 13.DependencyProperty.RegisterAttached("Command", typeof(ICommand), 14.typeof(SelectedItemChangedEventClass), new PropertyMetadata(OnSetCommandCallback)); 15.public static void OnSetCommandCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 16.{ 17.DataControl element = dependencyObject as DataControl; 18.if (element != null) 19.{ 20.SelectedItemChangedEventBehavior behavior = GetOrCreateBehavior(element); 21.behavior.Command = e.NewValue as ICommand; 22.} 23.} 24.#endregion 25.public static SelectedItemChangedEventBehavior GetOrCreateBehavior(DataControl element) 26.{ 27.SelectedItemChangedEventBehavior behavior = element.GetValue(SelectedItemChangedEventBehaviorProperty) as SelectedItemChangedEventBehavior; 28.if (behavior == null) 29.{ 30.behavior = new SelectedItemChangedEventBehavior(element); 31.element.SetValue(SelectedItemChangedEventBehaviorProperty, behavior); 32.} 33.return behavior; 34.} 35.public static SelectedItemChangedEventBehavior GetSelectedItemChangedEventBehavior(DependencyObject obj) 36.{ 37.return (SelectedItemChangedEventBehavior)obj.GetValue(SelectedItemChangedEventBehaviorProperty); 38.} 39.public static void SetSelectedItemChangedEventBehavior(DependencyObject obj, SelectedItemChangedEventBehavior value) 40.{ 41.obj.SetValue(SelectedItemChangedEventBehaviorProperty, value); 42.} 43.public static readonly DependencyProperty SelectedItemChangedEventBehaviorProperty = 44.DependencyProperty.RegisterAttached("SelectedItemChangedEventBehavior", 45.typeof(SelectedItemChangedEventBehavior), typeof(SelectedItemChangedEventClass), null); 46.} These end up looking very similar from command to command, but in a nutshell you create a command based on any event, determine what the parameter for it will be, then execute. It attaches via XAML and ties to a DelegateCommand in the viewmodel, so you get the full event experience (since some controls get a bit event-rich for added functionality). Simple enough, right? Viewmodel for the Job Posting View The Viewmodel is going to need to handle all events going back and forth, maintaining interactions with the data we are using, and both publishing and subscribing to events. Rather than breaking this into tons of little pieces, I'll give you a nice view of the entire viewmodel and then hit up the important points line-by-line: 001.public class JobPostingViewModel : ViewModelBase 002.{ 003.private readonly IEventAggregator eventAggregator; 004.private readonly IRegionManager regionManager; 005.public DelegateCommand<object> AddRecord { get; set; } 006.public DelegateCommand<object> EditRecord { get; set; } 007.public DelegateCommand<object> SelectedItemChanged { get; set; } 008.public RecruitingContext context; 009.private QueryableCollectionView _myJobs; 010.public QueryableCollectionView MyJobs 011.{ 012.get { return _myJobs; } 013.} 014.private QueryableCollectionView _selectionJobActionHistory; 015.public QueryableCollectionView SelectedJobActionHistory 016.{ 017.get { return _selectionJobActionHistory; } 018.} 019.private JobPosting _selectedJob; 020.public JobPosting SelectedJob 021.{ 022.get { return _selectedJob; } 023.set 024.{ 025.if (value != _selectedJob) 026.{ 027._selectedJob = value; 028.NotifyChanged("SelectedJob"); 029.} 030.} 031.} 032.public SubscriptionToken editToken = new SubscriptionToken(); 033.public SubscriptionToken addToken = new SubscriptionToken(); 034.public JobPostingViewModel(IEventAggregator eventAgg, IRegionManager regionmanager) 035.{ 036.// set Unity items 037.this.eventAggregator = eventAgg; 038.this.regionManager = regionmanager; 039.// load our context 040.context = new RecruitingContext(); 041.this._myJobs = new QueryableCollectionView(context.JobPostings); 042.context.Load(context.GetJobPostingsQuery()); 043.// set command events 044.this.AddRecord = new DelegateCommand<object>(this.AddNewRecord); 045.this.EditRecord = new DelegateCommand<object>(this.EditExistingRecord); 046.this.SelectedItemChanged = new DelegateCommand<object>(this.SelectedRecordChanged); 047.SetSubscriptions(); 048.} 049.#region DelegateCommands from View 050.public void AddNewRecord(object obj) 051.{ 052.this.eventAggregator.GetEvent<AddJobEvent>().Publish(true); 053.} 054.public void EditExistingRecord(object obj) 055.{ 056.if (_selectedJob == null) 057.{ 058.this.eventAggregator.GetEvent<NotifyUserEvent>().Publish("No job selected."); 059.} 060.else 061.{ 062.this._myJobs.EditItem(this._selectedJob); 063.this.eventAggregator.GetEvent<EditJobEvent>().Publish(this._selectedJob); 064.} 065.} 066.public void SelectedRecordChanged(object obj) 067.{ 068.if (obj.GetType() == typeof(ActionHistory)) 069.{ 070.// event bubbles up so we don't catch items from the ActionHistory grid 071.} 072.else 073.{ 074.JobPosting job = obj as JobPosting; 075.GrabHistory(job.PostingID); 076.} 077.} 078.#endregion 079.#region Subscription Declaration and Events 080.public void SetSubscriptions() 081.{ 082.EditJobCompleteEvent editComplete = eventAggregator.GetEvent<EditJobCompleteEvent>(); 083.if (editToken != null) 084.editComplete.Unsubscribe(editToken); 085.editToken = editComplete.Subscribe(this.EditCompleteEventHandler); 086.AddJobCompleteEvent addComplete = eventAggregator.GetEvent<AddJobCompleteEvent>(); 087.if (addToken != null) 088.addComplete.Unsubscribe(addToken); 089.addToken = addComplete.Subscribe(this.AddCompleteEventHandler); 090.} 091.public void EditCompleteEventHandler(bool complete) 092.{ 093.if (complete) 094.{ 095.JobPosting thisJob = _myJobs.CurrentEditItem as JobPosting; 096.this._myJobs.CommitEdit(); 097.this.context.SubmitChanges((s) => 098.{ 099.ActionHistory myAction = new ActionHistory(); 100.myAction.PostingID = thisJob.PostingID; 101.myAction.Description = String.Format("Job '{0}' has been edited by {1}", thisJob.JobTitle, "default user"); 102.myAction.TimeStamp = DateTime.Now; 103.eventAggregator.GetEvent<AddActionEvent>().Publish(myAction); 104.} 105., null); 106.} 107.else 108.{ 109.this._myJobs.CancelEdit(); 110.} 111.this.MakeMeActive(this.regionManager, "MainRegion", "JobPostingsView"); 112.} 113.public void AddCompleteEventHandler(JobPosting job) 114.{ 115.if (job == null) 116.{ 117.// do nothing, new job add cancelled 118.} 119.else 120.{ 121.this.context.JobPostings.Add(job); 122.this.context.SubmitChanges((s) => 123.{ 124.ActionHistory myAction = new ActionHistory(); 125.myAction.PostingID = job.PostingID; 126.myAction.Description = String.Format("Job '{0}' has been added by {1}", job.JobTitle, "default user"); 127.myAction.TimeStamp = DateTime.Now; 128.eventAggregator.GetEvent<AddActionEvent>().Publish(myAction); 129.} 130., null); 131.} 132.this.MakeMeActive(this.regionManager, "MainRegion", "JobPostingsView"); 133.} 134.#endregion 135.public void GrabHistory(int postID) 136.{ 137.context.ActionHistories.Clear(); 138._selectionJobActionHistory = new QueryableCollectionView(context.ActionHistories); 139.context.Load(context.GetHistoryForJobQuery(postID)); 140.} Taking it from the top, we're injecting an Event Aggregator and Region Manager for use down the road and also have the public DelegateCommands (just like in the Menu module). We also grab a reference to our context, which we'll obviously need for data, then set up a few fields with public properties tied to them. We're also setting subscription tokens, which we have not yet seen but I will get into below. The AddNewRecord (50) and EditExistingRecord (54) methods should speak for themselves for functionality, the one thing of note is we're sending events off to the Event Aggregator which some module, somewhere will take care of. Since these aren't entirely relying on one another, the Jobs View doesn't care if anyone is listening, but it will publish AddJobEvent (52), NotifyUserEvent (58) and EditJobEvent (63)regardless. Don't mind the GrabHistory() method so much, that is just grabbing history items (visibly being created in the SubmitChanges callbacks), and adding them to the database. Every action will trigger a history event, so we'll know who modified what and when, just in case. ;) So where are we at? Well, if we click to Add a job, we publish an event, if we edit a job, we publish an event with the selected record (attained through the magic of binding). Where is this all going though? To the Viewmodel, of course! XAML for the AddEditJobView This is pretty straightforward except for one thing, noted below: 001.<Grid x:Name="LayoutRoot" 002.Background="White"> 003.<Grid x:Name="xEditGrid" 004.Margin="10" 005.validationHelper:ValidationScope.Errors="{Binding Errors}"> 006.<Grid.Background> 007.<LinearGradientBrush EndPoint="0.5,1" 008.StartPoint="0.5,0"> 009.<GradientStop Color="#FFC7C7C7" 010.Offset="0" /> 011.<GradientStop Color="#FFF6F3F3" 012.Offset="1" /> 013.</LinearGradientBrush> 014.</Grid.Background> 015.<Grid.RowDefinitions> 016.<RowDefinition Height="40" /> 017.<RowDefinition Height="40" /> 018.<RowDefinition Height="40" /> 019.<RowDefinition Height="100" /> 020.<RowDefinition Height="100" /> 021.<RowDefinition Height="100" /> 022.<RowDefinition Height="40" /> 023.<RowDefinition Height="40" /> 024.<RowDefinition Height="40" /> 025.</Grid.RowDefinitions> 026.<Grid.ColumnDefinitions> 027.<ColumnDefinition Width="150" /> 028.<ColumnDefinition Width="150" /> 029.<ColumnDefinition Width="300" /> 030.<ColumnDefinition Width="100" /> 031.</Grid.ColumnDefinitions> 032.<!-- Title --> 033.<TextBlock Margin="8" 034.Text="{Binding AddEditString}" 035.TextWrapping="Wrap" 036.Grid.Column="1" 037.Grid.ColumnSpan="2" 038.FontSize="16" /> 039.<!-- Data entry area--> 040. 041.<TextBlock Margin="8,0,0,0" 042.Style="{StaticResource LabelTxb}" 043.Grid.Row="1" 044.Text="Job Title" 045.VerticalAlignment="Center" /> 046.<TextBox x:Name="xJobTitleTB" 047.Margin="0,8" 048.Grid.Column="1" 049.Grid.Row="1" 050.Text="{Binding activeJob.JobTitle, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}" 051.Grid.ColumnSpan="2" /> 052.<TextBlock Margin="8,0,0,0" 053.Grid.Row="2" 054.Text="Location" 055.d:LayoutOverrides="Height" 056.VerticalAlignment="Center" /> 057.<TextBox x:Name="xLocationTB" 058.Margin="0,8" 059.Grid.Column="1" 060.Grid.Row="2" 061.Text="{Binding activeJob.Location, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}" 062.Grid.ColumnSpan="2" /> 063. 064.<TextBlock Margin="8,11,8,0" 065.Grid.Row="3" 066.Text="Description" 067.TextWrapping="Wrap" 068.VerticalAlignment="Top" /> 069. 070.<TextBox x:Name="xDescriptionTB" 071.Height="84" 072.TextWrapping="Wrap" 073.ScrollViewer.VerticalScrollBarVisibility="Auto" 074.Grid.Column="1" 075.Grid.Row="3" 076.Text="{Binding activeJob.Description, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}" 077.Grid.ColumnSpan="2" /> 078.<TextBlock Margin="8,11,8,0" 079.Grid.Row="4" 080.Text="Requirements" 081.TextWrapping="Wrap" 082.VerticalAlignment="Top" /> 083. 084.<TextBox x:Name="xRequirementsTB" 085.Height="84" 086.TextWrapping="Wrap" 087.ScrollViewer.VerticalScrollBarVisibility="Auto" 088.Grid.Column="1" 089.Grid.Row="4" 090.Text="{Binding activeJob.Requirements, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}" 091.Grid.ColumnSpan="2" /> 092.<TextBlock Margin="8,11,8,0" 093.Grid.Row="5" 094.Text="Qualifications" 095.TextWrapping="Wrap" 096.VerticalAlignment="Top" /> 097. 098.<TextBox x:Name="xQualificationsTB" 099.Height="84" 100.TextWrapping="Wrap" 101.ScrollViewer.VerticalScrollBarVisibility="Auto" 102.Grid.Column="1" 103.Grid.Row="5" 104.Text="{Binding activeJob.Qualifications, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}" 105.Grid.ColumnSpan="2" /> 106.<!-- Requirements Checkboxes--> 107. 108.<CheckBox x:Name="xResumeRequiredCB" Margin="8,8,8,15" 109.Content="Resume Required" 110.Grid.Row="6" 111.Grid.ColumnSpan="2" 112.IsChecked="{Binding activeJob.NeedsResume, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}"/> 113. 114.<CheckBox x:Name="xCoverletterRequiredCB" Margin="8,8,8,15" 115.Content="Cover Letter Required" 116.Grid.Column="2" 117.Grid.Row="6" 118.IsChecked="{Binding activeJob.NeedsCV, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}"/> 119. 120.<CheckBox x:Name="xOverviewRequiredCB" Margin="8,8,8,15" 121.Content="Overview Required" 122.Grid.Row="7" 123.Grid.ColumnSpan="2" 124.IsChecked="{Binding activeJob.NeedsOverview, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}"/> 125. 126.<CheckBox x:Name="xJobActiveCB" Margin="8,8,8,15" 127.Content="Job is Active" 128.Grid.Column="2" 129.Grid.Row="7" 130.IsChecked="{Binding activeJob.IsActive, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}"/> 131. 132.<!-- Buttons --> 133. 134.<Button x:Name="xAddEditButton" Margin="8,8,0,10" 135.Content="{Binding AddEditButtonString}" 136.cal:Click.Command="{Binding AddEditCommand}" 137.Grid.Column="2" 138.Grid.Row="8" 139.HorizontalAlignment="Left" 140.Width="125" 141.telerik:StyleManager.Theme="Windows7" /> 142. 143.<Button x:Name="xCancelButton" HorizontalAlignment="Right" 144.Content="Cancel" 145.cal:Click.Command="{Binding CancelCommand}" 146.Margin="0,8,8,10" 147.Width="125" 148.Grid.Column="2" 149.Grid.Row="8" 150.telerik:StyleManager.Theme="Windows7" /> 151.</Grid> 152.</Grid> The 'validationHelper:ValidationScope' line may seem odd. This is a handy little trick for catching current and would-be validation errors when working in this whole setup. This all comes from an approach found on theJoy Of Code blog, although it looks like the story for this will be changing slightly with new advances in SL4/WCF RIA Services, so this section can definitely get an overhaul a little down the road. The code is the fun part of all this, so let us see what's happening under the hood. Viewmodel for the AddEditJobView We are going to see some of the same things happening here, so I'll skip over the repeat info and get right to the good stuff: 001.public class AddEditJobViewModel : ViewModelBase 002.{ 003.private readonly IEventAggregator eventAggregator; 004.private readonly IRegionManager regionManager; 005. 006.public RecruitingContext context; 007. 008.private JobPosting _activeJob; 009.public JobPosting activeJob 010.{ 011.get { return _activeJob; } 012.set 013.{ 014.if (_activeJob != value) 015.{ 016._activeJob = value; 017.NotifyChanged("activeJob"); 018.} 019.} 020.} 021. 022.public bool isNewJob; 023. 024.private string _addEditString; 025.public string AddEditString 026.{ 027.get { return _addEditString; } 028.set 029.{ 030.if (_addEditString != value) 031.{ 032._addEditString = value; 033.NotifyChanged("AddEditString"); 034.} 035.} 036.} 037. 038.private string _addEditButtonString; 039.public string AddEditButtonString 040.{ 041.get { return _addEditButtonString; } 042.set 043.{ 044.if (_addEditButtonString != value) 045.{ 046._addEditButtonString = value; 047.NotifyChanged("AddEditButtonString"); 048.} 049.} 050.} 051. 052.public SubscriptionToken addJobToken = new SubscriptionToken(); 053.public SubscriptionToken editJobToken = new SubscriptionToken(); 054. 055.public DelegateCommand<object> AddEditCommand { get; set; } 056.public DelegateCommand<object> CancelCommand { get; set; } 057. 058.private ObservableCollection<ValidationError> _errors = new ObservableCollection<ValidationError>(); 059.public ObservableCollection<ValidationError> Errors 060.{ 061.get { return _errors; } 062.} 063. 064.private ObservableCollection<ValidationResult> _valResults = new ObservableCollection<ValidationResult>(); 065.public ObservableCollection<ValidationResult> ValResults 066.{ 067.get { return this._valResults; } 068.} 069. 070.public AddEditJobViewModel(IEventAggregator eventAgg, IRegionManager regionmanager) 071.{ 072.// set Unity items 073.this.eventAggregator = eventAgg; 074.this.regionManager = regionmanager; 075. 076.context = new RecruitingContext(); 077. 078.AddEditCommand = new DelegateCommand<object>(this.AddEditJobCommand); 079.CancelCommand = new DelegateCommand<object>(this.CancelAddEditCommand); 080. 081.SetSubscriptions(); 082.} 083. 084.#region Subscription Declaration and Events 085. 086.public void SetSubscriptions() 087.{ 088.AddJobEvent addJob = this.eventAggregator.GetEvent<AddJobEvent>(); 089. 090.if (addJobToken != null) 091.addJob.Unsubscribe(addJobToken); 092. 093.addJobToken = addJob.Subscribe(this.AddJobEventHandler); 094. 095.EditJobEvent editJob = this.eventAggregator.GetEvent<EditJobEvent>(); 096. 097.if (editJobToken != null) 098.editJob.Unsubscribe(editJobToken); 099. 100.editJobToken = editJob.Subscribe(this.EditJobEventHandler); 101.} 102. 103.public void AddJobEventHandler(bool isNew) 104.{ 105.this.activeJob = null; 106.this.activeJob = new JobPosting(); 107.this.activeJob.IsActive = true; // We assume that we want a new job to go up immediately 108.this.isNewJob = true; 109.this.AddEditString = "Add New Job Posting"; 110.this.AddEditButtonString = "Add Job"; 111. 112.MakeMeActive(this.regionManager, "MainRegion", "AddEditJobView"); 113.} 114. 115.public void EditJobEventHandler(JobPosting editJob) 116.{ 117.this.activeJob = null; 118.this.activeJob = editJob; 119.this.isNewJob = false; 120.this.AddEditString = "Edit Job Posting"; 121.this.AddEditButtonString = "Edit Job"; 122. 123.MakeMeActive(this.regionManager, "MainRegion", "AddEditJobView"); 124.} 125. 126.#endregion 127. 128.#region DelegateCommands from View 129. 130.public void AddEditJobCommand(object obj) 131.{ 132.if (this.Errors.Count > 0) 133.{ 134.List<string> errorMessages = new List<string>(); 135. 136.foreach (var valR in this.Errors) 137.{ 138.errorMessages.Add(valR.Exception.Message); 139.} 140. 141.this.eventAggregator.GetEvent<DisplayValidationErrorsEvent>().Publish(errorMessages); 142. 143.} 144.else if (!Validator.TryValidateObject(this.activeJob, new ValidationContext(this.activeJob, null, null), _valResults, true)) 145.{ 146.List<string> errorMessages = new List<string>(); 147. 148.foreach (var valR in this._valResults) 149.{ 150.errorMessages.Add(valR.ErrorMessage); 151.} 152. 153.this._valResults.Clear(); 154. 155.this.eventAggregator.GetEvent<DisplayValidationErrorsEvent>().Publish(errorMessages); 156.} 157.else 158.{ 159.if (this.isNewJob) 160.{ 161.this.eventAggregator.GetEvent<AddJobCompleteEvent>().Publish(this.activeJob); 162.} 163.else 164.{ 165.this.eventAggregator.GetEvent<EditJobCompleteEvent>().Publish(true); 166.} 167.} 168.} 169. 170.public void CancelAddEditCommand(object obj) 171.{ 172.if (this.isNewJob) 173.{ 174.this.eventAggregator.GetEvent<AddJobCompleteEvent>().Publish(null); 175.} 176.else 177.{ 178.this.eventAggregator.GetEvent<EditJobCompleteEvent>().Publish(false); 179.} 180.} 181. 182.#endregion 183.} 184.} We start seeing something new on line 103- the AddJobEventHandler will create a new job and set that to the activeJob item on the ViewModel. When this is all set, the view calls that familiar MakeMeActive method to activate itself. I made a bit of a management call on making views self-activate like this, but I figured it works for one reason. As I create this application, views may not exist that I have in mind, so after a view receives its 'ping' from being subscribed to an event, it prepares whatever it needs to do and then goes active. This way if I don't have 'edit' hooked up, I can click as the day is long on the main view and won't get lost in an empty region. Total personal preference here. :) Everything else should again be pretty straightforward, although I do a bit of validation checking in the AddEditJobCommand, which can either fire off an event back to the main view/viewmodel if everything is a success or sent a list of errors to our notification module, which pops open a RadWindow with the alerts if any exist. As a bonus side note, here's what my WCF RIA Services metadata looks like for handling all of the validation: private JobPostingMetadata() { } [StringLength(2500, ErrorMessage = "Description should be more than one and less than 2500 characters.", MinimumLength = 1)] [Required(ErrorMessage = "Description is required.")] public string Description; [Required(ErrorMessage="Active Status is Required")] public bool IsActive; [StringLength(100, ErrorMessage = "Posting title must be more than 3 but less than 100 characters.", MinimumLength = 3)] [Required(ErrorMessage = "Job Title is required.")] public bool JobTitle; [Required] public string Location; public bool NeedsCV; public bool NeedsOverview; public bool NeedsResume; public int PostingID; [Required(ErrorMessage="Qualifications are required.")] [StringLength(2500, ErrorMessage="Qualifications should be more than one and less than 2500 characters.", MinimumLength=1)] public string Qualifications; [StringLength(2500, ErrorMessage = "Requirements should be more than one and less than 2500 characters.", MinimumLength = 1)] [Required(ErrorMessage="Requirements are required.")] public string Requirements;   The RecruitCB Alternative See all that Xaml I pasted above? Those are now two pieces sitting in the JobsView.xaml file now. The only real difference is that the xEditGrid now sits in the same place as xJobsGrid, with visibility swapping out between the two for a quick switch. I also took out all the cal: and command: command references and replaced Button events with clicks and the Grid selection command replaced with a SelectedItemChanged event. Also, at the bottom of the xEditGrid after the last button, I add a ValidationSummary (with Visibility=Collapsed) to catch any errors that are popping up. Simple as can be, and leads to this being the single code-behind file: 001.public partial class JobsView : UserControl 002.{ 003.public RecruitingContext context; 004.public JobPosting activeJob; 005.public bool isNew; 006.private ObservableCollection<ValidationResult> _valResults = new ObservableCollection<ValidationResult>(); 007.public ObservableCollection<ValidationResult> ValResults 008.{ 009.get { return this._valResults; } 010.} 011.public JobsView() 012.{ 013.InitializeComponent(); 014.this.Loaded += new RoutedEventHandler(JobsView_Loaded); 015.} 016.void JobsView_Loaded(object sender, RoutedEventArgs e) 017.{ 018.context = new RecruitingContext(); 019.xJobsGrid.ItemsSource = context.JobPostings; 020.context.Load(context.GetJobPostingsQuery()); 021.} 022.private void xAddRecordButton_Click(object sender, RoutedEventArgs e) 023.{ 024.activeJob = new JobPosting(); 025.isNew = true; 026.xAddEditTitle.Text = "Add a Job Posting"; 027.xAddEditButton.Content = "Add"; 028.xEditGrid.DataContext = activeJob; 029.HideJobsGrid(); 030.} 031.private void xEditRecordButton_Click(object sender, RoutedEventArgs e) 032.{ 033.activeJob = xJobsGrid.SelectedItem as JobPosting; 034.isNew = false; 035.xAddEditTitle.Text = "Edit a Job Posting"; 036.xAddEditButton.Content = "Edit"; 037.xEditGrid.DataContext = activeJob; 038.HideJobsGrid(); 039.} 040.private void xAddEditButton_Click(object sender, RoutedEventArgs e) 041.{ 042.if (!Validator.TryValidateObject(this.activeJob, new ValidationContext(this.activeJob, null, null), _valResults, true)) 043.{ 044.List<string> errorMessages = new List<string>(); 045.foreach (var valR in this._valResults) 046.{ 047.errorMessages.Add(valR.ErrorMessage); 048.} 049.this._valResults.Clear(); 050.ShowErrors(errorMessages); 051.} 052.else if (xSummary.Errors.Count > 0) 053.{ 054.List<string> errorMessages = new List<string>(); 055.foreach (var err in xSummary.Errors) 056.{ 057.errorMessages.Add(err.Message); 058.} 059.ShowErrors(errorMessages); 060.} 061.else 062.{ 063.if (this.isNew) 064.{ 065.context.JobPostings.Add(activeJob); 066.context.SubmitChanges((s) => 067.{ 068.ActionHistory thisAction = new ActionHistory(); 069.thisAction.PostingID = activeJob.PostingID; 070.thisAction.Description = String.Format("Job '{0}' has been edited by {1}", activeJob.JobTitle, "default user"); 071.thisAction.TimeStamp = DateTime.Now; 072.context.ActionHistories.Add(thisAction); 073.context.SubmitChanges(); 074.}, null); 075.} 076.else 077.{ 078.context.SubmitChanges((s) => 079.{ 080.ActionHistory thisAction = new ActionHistory(); 081.thisAction.PostingID = activeJob.PostingID; 082.thisAction.Description = String.Format("Job '{0}' has been added by {1}", activeJob.JobTitle, "default user"); 083.thisAction.TimeStamp = DateTime.Now; 084.context.ActionHistories.Add(thisAction); 085.context.SubmitChanges(); 086.}, null); 087.} 088.ShowJobsGrid(); 089.} 090.} 091.private void xCancelButton_Click(object sender, RoutedEventArgs e) 092.{ 093.ShowJobsGrid(); 094.} 095.private void ShowJobsGrid() 096.{ 097.xAddEditRecordButtonPanel.Visibility = Visibility.Visible; 098.xEditGrid.Visibility = Visibility.Collapsed; 099.xJobsGrid.Visibility = Visibility.Visible; 100.} 101.private void HideJobsGrid() 102.{ 103.xAddEditRecordButtonPanel.Visibility = Visibility.Collapsed; 104.xJobsGrid.Visibility = Visibility.Collapsed; 105.xEditGrid.Visibility = Visibility.Visible; 106.} 107.private void ShowErrors(List<string> errorList) 108.{ 109.string nm = "Errors received: \n"; 110.foreach (string anerror in errorList) 111.nm += anerror + "\n"; 112.RadWindow.Alert(nm); 113.} 114.} The first 39 lines should be pretty familiar, not doing anything too unorthodox to get this up and running. Once we hit the xAddEditButton_Click on line 40, we're still doing pretty much the same things except instead of checking the ValidationHelper errors, we both run a check on the current activeJob object as well as check the ValidationSummary errors list. Once that is set, we again use the callback of context.SubmitChanges (lines 68 and 78) to create an ActionHistory which we will use to track these items down the line. That's all? Essentially... yes. If you look back through this post, most of the code and adventures we have taken were just to get things working in the MVVM/Prism setup. Since I have the whole 'module' self-contained in a single JobView+code-behind setup, I don't have to worry about things like sending events off into space for someone to pick up, communicating through an Infrastructure project, or even re-inventing events to be used with attached behaviors. Everything just kinda works, and again with much less code. Here's a picture of the MVVM and Code-behind versions on the Jobs and AddEdit views, but since the functionality is the same in both apps you still cannot tell them apart (for two-strike): Looking ahead, the Applicants module is effectively the same thing as the Jobs module, so most of the code is being cut-and-pasted back and forth with minor tweaks here and there. So that one is being taken care of by me behind the scenes. Next time, we get into a new world of fun- the interview scheduling module, which will pull from available jobs and applicants for each interview being scheduled, tying everything together with RadScheduler to the rescue. Did you know that DotNetSlackers also publishes .net articles written by top known .net Authors? We already have over 80 articles in several categories including Silverlight. Take a look: here.

    Read the article

  • Best Design Pattern for Coupling User Interface Components and Data Structures

    - by szahn
    I have a windows desktop application with a tree view. Due to lack of a sound data-binding solution for a tree view, I've implemented my own layer of abstraction on it to bind nodes to my own data structure. The requirements are as follows: Populate a tree view with nodes that resemble fields in a data structure. When a node is clicked, display the appropriate control to modify the value of that property in the instance of the data structure. The tree view is populated with instances of custom TreeNode classes that inherit from TreeNode. The responsibility of each custom TreeNode class is to (1) format the node text to represent the name and value of the associated field in my data structure, (2) return the control used to modify the property value, (3) get the value of the field in the control (3) set the field's value from the control. My custom TreeNode implementation has a property called "Control" which retrieves the proper custom control in the form of the base control. The control instance is stored in the custom node and instantiated upon first retrieval. So each, custom node has an associated custom control which extends a base abstract control class. Example TreeNode implementation: //The Tree Node Base Class public abstract class TreeViewNodeBase : TreeNode { public abstract CustomControlBase Control { get; } public TreeViewNodeBase(ExtractionField field) { UpdateControl(field); } public virtual void UpdateControl(ExtractionField field) { Control.UpdateControl(field); UpdateCaption(FormatValueForCaption()); } public virtual void SaveChanges(ExtractionField field) { Control.SaveChanges(field); UpdateCaption(FormatValueForCaption()); } public virtual string FormatValueForCaption() { return Control.FormatValueForCaption(); } public virtual void UpdateCaption(string newValue) { this.Text = Caption; this.LongText = newValue; } } //The tree node implementation class public class ExtractionTypeNode : TreeViewNodeBase { private CustomDropDownControl control; public override CustomControlBase Control { get { if (control == null) { control = new CustomDropDownControl(); control.label1.Text = Caption; control.comboBox1.Items.Clear(); control.comboBox1.Items.AddRange( Enum.GetNames( typeof(ExtractionField.ExtractionType))); } return control; } } public ExtractionTypeNode(ExtractionField field) : base(field) { } } //The custom control base class public abstract class CustomControlBase : UserControl { public abstract void UpdateControl(ExtractionField field); public abstract void SaveChanges(ExtractionField field); public abstract string FormatValueForCaption(); } //The custom control generic implementation (view) public partial class CustomDropDownControl : CustomControlBase { public CustomDropDownControl() { InitializeComponent(); } public override void UpdateControl(ExtractionField field) { //Nothing to do here } public override void SaveChanges(ExtractionField field) { //Nothing to do here } public override string FormatValueForCaption() { //Nothing to do here return string.Empty; } } //The custom control specific implementation public class FieldExtractionTypeControl : CustomDropDownControl { public override void UpdateControl(ExtractionField field) { comboBox1.SelectedIndex = comboBox1.FindStringExact(field.Extraction.ToString()); } public override void SaveChanges(ExtractionField field) { field.Extraction = (ExtractionField.ExtractionType) Enum.Parse(typeof(ExtractionField.ExtractionType), comboBox1.SelectedItem.ToString()); } public override string FormatValueForCaption() { return string.Empty; } The problem is that I have "generic" controls which inherit from CustomControlBase. These are just "views" with no logic. Then I have specific controls that inherit from the generic controls. I don't have any functions or business logic in the generic controls because the specific controls should govern how data is associated with the data structure. What is the best design pattern for this?

    Read the article

  • Silverlight Binding with multiple collections

    - by George Evjen
    We're designing some sport specific applications. In one of our views we have a gridview that is bound to an observable collection of Teams. This is pretty straight forward in terms of getting Teams bound to the GridView. <telerik:RadGridView Grid.Row="0" Grid.Column="0" x:Name="UsersGrid" ItemsSource="{Binding TeamResults}" SelectedItem="{Binding SelectedTeam, Mode=TwoWay}"> <telerik:RadGridView.Columns> <telerik:GridViewDataColumn Header="Name/Group" DataMemberBinding="{Binding TeamName}" MinWidth="150"></telerik:GridViewDataColumn> </telerik:RadGridView.Columns> </telerik:RadGridView> We use the observable collection of teams as our items source and then bind the property of TeamName to the first column. You can set the binding to mode=TwoWay, we use a dialog where we edit the selected item, so our binding here is not set to two way. The issue comes when we want to bind to a property that has another collection in it. To continue on our code from above, we have an observable collection of teams, within that collection we have a collection of KeyPeople. We get this collection using RIA Serivces with the code below. return _TeamsRepository.All().Include("KeyPerson"); Here we are getting all the teams and also including the KeyPerson entity. So when we are done with our Load we will end up with an observable collection of Teams with a navigation property / entity of KeyPerson. Within this KeyPerson entity is a list of people associated with that particular team. We want to display the head coach from this list of KeyPersons. This list currently has a list of ten or more people that are bound to this team, but we just want to display the Head Coach in the column next to team name. The issue becomes how do we bind to this included entity? I have found about three different ways to solve this issue. The way that seemed to fit us best is to utilize the features within RIA Services. We can create client side properties that will do the work for us. We will create in the client side library a partial class of Team. We will end up in our library a file that is Team.shared.cs. The code below is what we will put into our partial team class. public KeyPerson Coach        {            get            {                if (this.KeyPerson != null && this.KeyPerson.Any())                { return this.KeyPerson.Where(x => x.RelationshipType == “HeadCoach”).FirstOrDefault(); }                 return null;            }        } We will return just the person that is the Head Coach and then be able to bind that and any other additional properties that we need. <telerik:GridViewDataColumn Header="Coach" DataMemberBinding="{Binding Coach.Name}" MinWidth="150"></telerik:GridViewDataColumn> There are other ways that we could have solved this issue but we felt that creating a partial class through RIA Services best suited our needs.

    Read the article

  • wpf DataGrid.datagridtemplatecolumn combobox does not update itemssource

    - by David
    <Grid Loaded="Grid_Loaded"> <DataGrid Margin="10,10,10,162" x:Name="dataGrid1" ItemsSource="{Binding myItemsSource}"/> <DataGrid Margin="10,164,10,10" x:Name="dataGrid2" ItemsSource="{Binding myItemsSource}" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Header="A" Binding="{Binding A}"></DataGridTextColumn> <DataGridComboBoxColumn Header="B" TextBinding="{Binding B}" x:Name="columnB"></DataGridComboBoxColumn> <DataGridTemplateColumn Header="C" x:Name="columnC"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <ComboBox Text="{Binding C, Mode=TwoWay}" SelectedItem="{Binding C, Mode=TwoWay}"> <ComboBoxItem Content="AAA"/> <ComboBoxItem Content="BBB"/> <ComboBoxItem Content="CCC"/> <ComboBoxItem Content="XXX"/> <ComboBoxItem Content="YYY"/> <ComboBoxItem Content="ZZZ"/> </ComboBox> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> columnB (buidin DataGridComboBoxColumn) is working. columnB.ItemsSource = LstForCbx; public List LstForCbx = new List{"AAA", "BBB", "CCC", "XXX", "YYY", "ZZZ"}; columnC combobox in DataGridComboBoxColumn not working. What wrong with my code?

    Read the article

  • ListView setOnItemClickListener and setOnItemSelectedListener to store the Selected Item Index

    - by Christophe
    Hi all, I have read on this site that it is necessary to customize the setOnItemSelectedListener and setOnItemClickListener of a ListView if we want to know the Index of the SelectedItem (.getSelectedItemPosition()). So that is what I do but it does not stores the position of the SekectedItem, instead i have always -1... What I want to do is just to give the user a way to delete items from a list by selected and Item and Clicking a button. See the code below : listViewPeople.setOnItemClickListener(new ListView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> a, View v, int i, long l) { try { // Remembers the selected Index listViewPeopleId = listViewPeople.getSelectedItemPosition(); } catch(Exception e) { System.out.println("Nay, cannot get the selected index"); } } }); listViewPeople.setOnItemSelectedListener(new ListView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> a, View v, int i, long l) { try { // Remembers the selected Index listViewPeopleId = listViewPeople.getSelectedItemPosition(); System.out.println("Yay, set the selected index " + listViewPeopleId); } catch(Exception e) { System.out.println("Nay, cannot get the selected index " + listViewPeopleId); } } @Override public void onNothingSelected(AdapterView<?> arg0) { try { // Remembers nothing selected listViewPeopleId = -1; System.out.println("Yay, set that nothing is selected " + listViewPeopleId); } catch(Exception e) { System.out.println("Nay, cannot set that nothing is selected " + listViewPeopleId); } } }); What's wrong?? Thank you for your help! Christophe

    Read the article

  • Listview of items from a object selected in another listview

    - by Ingó Vals
    Ok the title maybe a little confusing. I have a database with the table Companies wich has one-to-many relotionship with another table Divisions ( so each company can have many divisions ) and division will have many employees. I have a ListView of the companies. What I wan't is that when I choose a company from the ListView another ListView of divisions within that company appears below it. Then I pick a division and another listview of employees within that division appaers below that. You get the picture. Is there anyway to do this mostly inside the XAML code declaritively (sp?). I'm using linq so the Company entity objects have a property named Division wich if I understand linq correctly should include Division objects of the divisions connected to the company. So after getting all the companies and putting them as a itemsource to CompanyListView this is where I currently am. <ListView x:Name="CompanyListView" DisplayMemberPath="CompanyName" Grid.Row="0" Grid.Column="0" /> <ListView DataContext="{Binding ElementName=CompanyListView, Path=SelectedItem}" DisplayMemberPath="Division.DivisionName" Grid.Row="1" Grid.Column="0" /> I know I'm way off but I was hoping by putting something specific in the DataContext and DisplayMemberPath I could get this to work. If not then I have to capture the Id of the company I guess and capture a select event or something. Another issue but related is the in the seconde column besides the lisview I wan't to have a details/edit view for the selected item. So when only a company is selected details about that will appear then when a division under the company is picked It will go there instead, any ideas?

    Read the article

  • DynamicResource and Dynamic Items in ContextMenu on XamDataGrid

    - by miguel
    I would like to dynamically create a set of context menu options based upon some properties. Currently, I am creating a context menu as a DynamicResource with the visibility of the menu options bound to the properties, however, it seems that the DynamicResource is created only once, at runtime. Is this true? What I would like to do is have the menu generated each time, which will take into account the property changes on the data object. Please see the following XAML snippet: <Border DockPanel.Dock="Right" Margin="4,4,4,4" BorderBrush="Gray" BorderThickness="1" CornerRadius="3" > <igDP:XamDataGrid Height="Auto" Width="Auto" Style="{DynamicResource DefaultInfragisticsGridStyle}" Name="axeDataGrid" ActiveRecord="{Binding Path=SelectedItem, Mode=TwoWay}" DataSource="{Binding Path=Axes}" ContextMenuOpening="ContextMenuOpeningHandler"> <igDP:XamDataGrid.Resources> <Style TargetType="{x:Type igDP:DataRecordPresenter}" BasedOn="{x:Static Themes:DataPresenterAero.DataRecordPresenter}"/> <ContextMenu x:Key="RecordContextMenu"> <ContextMenu.Resources> <BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter"/> </ContextMenu.Resources> <MenuItem Header="Cancel Axe" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type igDP:XamDataGrid}}, Path=DataContext.CancelAxe}" Visibility="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type igDP:XamDataGrid}}, Path=DataContext.IsCancelAxeAllowed, Converter={StaticResource booleanToVisibilityConverter}, Mode=OneWay}"/> <MenuItem Header="Create RFQ" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type igDP:XamDataGrid}}, Path=DataContext.CreateRFQ}" Visibility="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type igDP:XamDataGrid}}, Path=DataContext.IsCreateRfqAllowed, Converter={StaticResource booleanToVisibilityConverter}, Mode=OneWay}"/> </ContextMenu> <Style TargetType="{x:Type igDP:DataRecordCellArea}"> <Setter Property="ContextMenu" Value="{DynamicResource RecordContextMenu}" /> </Style>

    Read the article

  • WPF AutoCompleteBox with ability to add new values to list.

    - by WillH
    Hi, I would like to use autocompletebox with a list of values, but also add new values to the list if a user enters one that isn't present. I currently have a string property in my view model called 'Comment'. Currently this is bound to a textbox in the view - user types a comment and the view model is updated. Simple. To save time, my customer would like it to autocomplete from previous values, so the way I thought to do this is something like: ViewModel public string Comment; public ObservableCollection<string> CommentsList { ... } (populate the CommentsList when the viewmodel is created) View <AutoCompleteComboBox ItemsSource="{Binding CommentsList}" SelectedItem="{Binding Comment, Mode=TwoWay/> So when the user selects a value, it saves the value in the Comment property. This works fine if the user selects an item in the list, but if the user types in a new value, the comment property is not updated (it is null because the selected item was not in the list). Is this possible with autocompletebox? Thanks in advance, Will

    Read the article

  • Databinding between UserControls?

    - by Dave
    I've got a situation where one of my UserControls would like to display a list of strings in a droplist, and the ItemsSource is set to another UserControl's ObservableCollection. The consumer of this data has its droplist defined in XAML like this: <ComboBox Grid.Column="1" SelectedItem="{Binding MyItem, Mode=TwoWay}" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.MyItems}" Margin="3"></ComboBox> MyItems is defined as an ObservableCollection<string> in the producer UserControl. Now everything works fine when the controls are loaded. As long as MyItems is populated first, and then the consumer UserControl is displayed, all of the items are there. I obviously don't get any errors in the Output Window or anything like that. The issue I have is that when the ObservableCollection is modified, those changes are not reflected in the consumer UserControl! I've never had this problem before, but all of my previous uses of ObservableCollection with updating the collection are within a single control, and databinding is not inter-UserControl. Is there something I did wrong? Is there a good way to actually debug this? Reed Copsey indicates here that inter-UserControl databinding is possible. Unfortunately, my favorite Bea Stollnitz article on WPF databinding debugging doesn't suggest anything that I could use for this particular problem.

    Read the article

  • MVVM Madness: Commands

    - by JP
    I like MVVM. I don't love it, but like it. Most of it makes sense. But, I keep reading articles that encourage you to write a lot of code so that you can write XAML and don't have to write any code in the code-behind. Let me give you an example. Recently I wanted to hookup a command in my ViewModel to a ListView MouseDoubleClickEvent. I wasn't quite sure how to do this. Fortunately, Google has answers for everything. I found the following articles: http://blog.functionalfun.net/2008/09/hooking-up-commands-to-events-in-wpf.html http://joyfulwpf.blogspot.com/2009/05/mvvm-invoking-command-on-attached-event.html http://sachabarber.net/?p=514 http://geekswithblogs.net/HouseOfBilz/archive/2009/08/27/adventures-in-mvvm-ndash-binding-commands-to-any-event.aspx http://marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/ While the solutions were helpful in my understanding of commands, there were problems. Some of the aforementioned solutions rendered the WPF designer unusable because of a common hack of appending "Internal" after a dependency property; the WPF designer can't find it, but the CLR can. Some of the solutions didn't allow multiple commands to the same control. Some of the solutions didn't allow parameters. After experimenting for a few hours I just decided to do this: private void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e) { ListView lv = sender as ListView; MyViewModel vm = this.DataContext as MyViewModel; vm.DoSomethingCommand.Execute(lv.SelectedItem); } So, MVVM purists, please tell me what's wrong with this? I can still Unit test my command. This seems very practical, but seems to violate the guideline of "ZOMG... you have code in your code-behind!!!!" Please share your thoughts. Thanks in advance.

    Read the article

  • silverlight master-detail with two listboxes in pure xaml with ria services throwing exception

    - by Sam
    Hi, I was trying to achieve master-detail with 2 ListBox, 2 DomainDataSource and a IValueConverter, when entering the page it throws the random error it does when your xaml is invalid: "AG_E_PARSER_BAD_PROPERTY_VALUE [Line: 24 Position: 61]" Which is in fact the start position of where I am binding the listbox selected item with converter to the parameter's value of my DomainDataSource. I would love to achieve this by pure xaml, I did it by code behind and that works but I don't like it :p When the parameter is a hard-coded integer 1, it works, so I assume it's the value binding My code is below here, thanks in advance for at least looking :) (taken into accound all the xmlns's & usings are correct) Xaml: <Grid x:Name="LayoutRoot"> <Grid.Resources> <helpers:ListItemtoIdListValueConverter x:Key="mListConverter" /> </Grid.Resources> <riacontrols:DomainDataSource x:Name="GetLists" DomainContext="{StaticResource DbContext}" LoadSize="20" QueryName="GetLists" AutoLoad="True" /> <riacontrols:DomainDataSource x:Name="GetListItems" DomainContext="{StaticResource DbContext}" LoadSize="20" QueryName="GetListItemsById" AutoLoad="True"> <riacontrols:DomainDataSource.QueryParameters> <riadata:Parameter ParameterName="id" Value="{Binding ElementName=ListBoxLists, Path=SelectedItem, Converter={StaticResource mListConverter}}" /> </riacontrols:DomainDataSource.QueryParameters> </riacontrols:DomainDataSource> <activity:Activity IsActive="{Binding IsBusy, ElementName=ListBoxListItems}"> <StackPanel Orientation="Horizontal"> <ListBox x:Name="ListBoxLists" ItemsSource="{Binding Data, ElementName=GetLists, Mode=OneWay}" Width="150" Margin="0,0,10,10" /> <ListBox x:Name="ListBoxListItems" ItemsSource="{Binding Data, ElementName=GetListItems, Mode=OneWay}" Width="150" Margin="0,0,10,10" /> </StackPanel> </activity:Activity> </Grid> IValueConverter: public class ListItemtoIdListValueConverter: IValueConverter { #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { list mList = (list)value; if (mList != null) return mList.id; else return null; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } #endregion }

    Read the article

  • Binding from View-Model to View-Model of a child User Control in Silverlight? 2 sources - 1 target..

    - by andrej351
    Hi there, So i have a UserControl for one of my Views and have another 'child' UserControl inside that. The outer 'parent' UserControl has a Collection on its View-Model and a Grid control on it to display a list of Items. I want to place another UserControl inside this UserControl to display a form representing the details of one Item. The outer / parent UserControl's View-Model already has a property on it to hold the currently selected Item and i would like to bind this to a DependancyProperty on the inner / child UserControl. I would then like to bind that DependancyProperty to a property on the child UserControl's View-Model. I can then set the DependancyProperty once in XAML with a binding expression and have the child UserControl do all its work in its View-Model like it should. The code i have looks like this.. Parent UserControl: <UserControl x:Class="ItemsListView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" DataContext="{Binding Source={StaticResource ServiceLocator}, Path=ItemsListViewModel}"> <!-- Grid Control here... --> <ItemDetailsView Item="{Binding Source={StaticResource ServiceLocator}, Path=ItemsListViewModel.SelectedItem}" /> </UserControl> Child UserControl: <UserControl x:Class="ItemDetailsView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" DataContext="{Binding Source={StaticResource ServiceLocator}, Path=ItemDetailsViewModel}" ItemDetailsView.Item="{Binding Source={StaticResource ServiceLocator}, Path=ItemDetailsViewModel.Item, Mode=TwoWay}"> <!-- Form controls here... --> </UserControl> The selected Item is bound to the DependancyProperty fine. However from the DependancyProperty to the child View-Model does not. It appears to be a situation where there are two concurrent bindings which need to work but with the same target for two sources. Why won't the second (in the child UserControl) binding work?? Is there a way to acheive the behaviour I'm after?? Cheers.

    Read the article

  • MSMQ first Message.Body in queue is OK, all following Message.Body in queue are empty

    - by Andrew A
    I send a handful of identical (except for Id#, obviously) messages to an MSMQ queue on my local machine. The body of the messages is a serialized XElement object. When I try to process the first message in the queue, I am able to successfully de-serialize the Message.Body object and save it to file. However, when trying to process the next (or any subsequent) message, the Message.Body is absent, and an exception is thrown. I have verified the Message ID's are correct for the message attempting to be processed. The XML being serialized is properly formed. Any ideas? I am basing my code on the Microsoft MSMQ Book order sample found here: http://msdn.microsoft.com/en-us/library/ms180970%28VS.80%29.aspx // Create Envelope XML object XElement envelope = new XElement(env + "Envelope", new XAttribute(XNamespace.Xmlns + "env", env.NamespaceName) <snip> //Send envelope as message body MessageQueue myQueue = new MessageQueue(String.Format(@"FORMATNAME:DIRECT=OS:localhost\private$\mqsample")); myQueue.DefaultPropertiesToSend.Recoverable = true; // Prepare message Message myMessage = new Message(); myMessage.ResponseQueue = new MessageQueue(String.Format(System.Globalization.CultureInfo.InvariantCulture, @"FORMATNAME:DIRECT=TCP:192.168.1.217\private$\mqdemoAck")); myMessage.Body = envelope; // Send the message into the queue. myQueue.Send(myMessage,"message label"); //Retrieve messages from queue LabelIdMapping labelID = (LabelIdMapping)mqlistBox3.SelectedItem; System.Messaging.Message message = mqOrderQueue.ReceiveById(labelID.Id); The Message.Body value I see on the 1st retrieve is as expected: <?xml version="1.0" encoding="utf-8"?> <string>Some String</string> However, the 2nd and subsequent retrieve operations Message.Body is: "Cannot deserialize the message passed as an argument. Cannot recognize the serialization format." How does this work fine the first time but not after that? I have tried message.Dispose() after retrieving it but it did not help. Thank you very much for any help on this!

    Read the article

  • “if” statement vs OO Design - 2

    - by hilal
    I encountered similar problem “if” statement vs OO Design - 1 but it is slightly different. Here is the problem that open the popup (different objects/popups) onValueChange of listbox Popup1 p1; // different objects Popup2 p2; // different objects Popup3 p3; ... listbox.add("p1"); listbox.add("p2"); listbox.add("p3"); ... listbox.addChangeHandler() { if(getSelectedItem().equals("p1")){ p1 = new Popup1(); p1.show(); } else if() {...} .... } I don't want to write "if" that if p1 then p1 = new Popup1(); p1.center(); How I can handle this situation? Any design-pattern? Here is my solution but it is so costly map() { map.put("p1", new Popup1()); map.put("p2", new Popup2()); map.put("p3", new Popup3()); } onValueChange() { map.get(selectedItem).show(); } One drawback is initialization all the popups. but it is require only when valueChange

    Read the article

  • WPF ComboBox IsSynchronised Default Value

    - by LnDCobra
    I am trying to display a default value (or even NO value) when selected index is -1, or selecteditem is null. This normally works perfectly fine but when I enable IsSynchronizedWithCurrentItem and set it to True, the first value in my DataTable gets displayed. How can I have both IsSynchronizedWithCurrentItem ="True" and show no/default value when it is loaded. My Combo Box XAML: <GroupBox Name="ClientGroup" Header="Client" Margin="63,182,0,177" FontSize="14" HorizontalAlignment="Left" Width="298"> <ComboBox Name="Supplier" Grid.IsSharedSizeScope="True" ItemsSource="{Binding}" IsEditable="True" Text="Please Choose..." TextSearch.TextPath="CompanyName" IsSynchronizedWithCurrentItem="True" Height="23" VerticalAlignment="Top" Margin="0,6,6,0" FontSize="11" StaysOpenOnEdit="True"> <ComboBox.ItemTemplate> <DataTemplate> <Grid Margin="0,5,0,5"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" SharedSizeGroup="CompanyName" /> <ColumnDefinition Width="Auto" SharedSizeGroup="EIC" /> </Grid.ColumnDefinitions> <TextBlock Text="{Binding CompanyName}" Grid.Column="0" /> <TextBlock Text="{Binding EIC, StringFormat=' ({0})'}" Grid.Column="1" FontFamily="Courier New" FontWeight="Bold" FontSize="12" /> </Grid> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> </GroupBox> My CS code behind: ClientGroup.DataContext = (new CompanyDealsDataSetTableAdapters.CompanyTableAdapter()).GetData(); When I start my application it automatically selects the first row in my data table. It works as expected when I remove IsSynchronizedWithCurrentItem. Any ideas?

    Read the article

  • Idiomatic default sort using WCF RIA, EF4, Silverlight?

    - by Duncan Bayne
    I've got two Silverlight 4.0 ComboBoxes; the second displays the children of the entity selected in the first: <ComboBox Name="cmbThings" ItemsSource="{Binding Path=Things,Mode=TwoWay}" DisplayMemberPath="Name" SelectionChanged="CmbThingsSelectionChanged" /> <ComboBox Name="cmbChildThings" ItemsSource="{Binding Path=SelectedThing.ChildThings,Mode=TwoWay}" DisplayMemberPath="Name" /> The code behind the view provides a (simple, hacky) way to databind those ComboBoxes, by loading Entity Framework 4.0 entities through a WCF RIA service: public EntitySet<Thing> Things { get; private set; } public Thing SelectedThing { get; private set; } protected override void OnNavigatedTo(NavigationEventArgs e) { var context = new SortingDomainContext(); context.Load(context.GetThingsQuery()); context.Load(context.GetChildThingsQuery()); Things = context.Things; DataContext = this; } private void CmbThingsSelectionChanged(object sender, SelectionChangedEventArgs e) { SelectedThing = (Thing) cmbThings.SelectedItem; if (PropertyChanged != null) { PropertyChanged.Invoke(this, new PropertyChangedEventArgs("SelectedThing")); } } public event PropertyChangedEventHandler PropertyChanged; What I'd like to do is have both combo boxes sort their contents alphabetically, and I'd like to specify that behaviour in the XAML if at all possible. Could someone please tell me what is the idiomatic way of doing this with the SL4 / EF4 / WCF RIA technology stack?

    Read the article

  • Trigger for ComboBox in Silverlight

    - by Budda
    Is there any possibility to display selected item of the ComboBox (after popup closing) in a way that is different from its displaying in DropDown List (There are players number and name in the dropdown list, but after list closing I want to see only its number). How can I change a background for the player with some Flag? As far as I know, all of that can be done with triggers, but are they supported in Silverlight 4, VS2010, Silverlight Toolkit 4? In my case the following code <ComboBox ItemsSource="{Binding PlayersAll}" SelectedItem="{Binding Path=SelectedPlayer, Mode=TwoWay}" > <ComboBox.ItemTemplate> <DataTemplate> <ToolkitControls:WrapPanel Orientation="Horizontal"> <TextBlock Text="{Binding TeamNumber}"/> <TextBlock Text=" - "/> <TextBlock Text="{Binding ShortName}"/> </ToolkitControls:WrapPanel> <DataTemplate.Triggers> <Trigger Property="HasError" Value="True"> <Setter Property="Background" TargetName="FlagSet" Value="Red"/> </Trigger> </DataTemplate.Triggers> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> gives an error: The property 'Triggers' does not exist on the type 'DataTemplate' in the XML namespace 'http://schemas.microsoft.com/winfx/2006/xaml/presentation' what is wrong here? Here are my namespaces: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" xmlns:ToolkitControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit"

    Read the article

  • Conditional Drag and Drop Operations in Flex/AS3 Tree

    - by user163757
    Good day everyone. I am currently working with a hierarchical tree structure in AS3/Flex, and want to enable drag and drop capabilities under certain conditions: Only parent/top level nodes can be moved Parent/top level nodes must remain at this level; they can not be moved to child nodes of other parent nodes Using the dragEnter event of the tree, I am able to handle condition 1 easily. private function onDragEnter(event:DragEvent):void { // only parent nodes (map layers) are moveable event.preventDefault(); if(toc.selectedItem.hasOwnProperty("layer")) DragManager.acceptDragDrop(event.target as UIComponent); else DragManager.showFeedback(DragManager.NONE); } Handling the second condition is proving to be a bit more difficult. I am pretty sure the dragOver event is the place for logic. I have been experimenting with calculateDropIndex, but that always gives me the index of the parent node, which doesn't help check if the potential drop location is acceptable or not. Below is some pseudo code of what I am looking to accomplish. private function onDragOver(e:DragEvent):void { // if potential drop location has parents // dont allow drop // else // allow drop } Can anyone provide advice how to implement this?

    Read the article

  • BackgroundWorker Not working in VSTO

    - by Chris
    I have a background worker. Before I invoke the worker I disable a button and make a gif visible. I then invoke the runworkerasync method and it runs fine until comleteion. On the 'RunWorkerCompleted()' I get a cross thread error. Any idea why? private void buttonRun_Click(object sender, EventArgs e) { if (comboBoxFiscalYear.SelectedIndex != -1 && !string.IsNullOrEmpty(textBoxFolderLoc.Text)) { try { u = new UpdateDispositionReports( Convert.ToInt32(comboBoxFiscalYear.SelectedItem.ToString()) , textBoxFolderLoc.Text , Properties.Settings.Default.TemplatePath , Properties.Settings.Default.ConnStr); this.buttonRun.Enabled = false; this.pictureBox1.Visible = true; BackgroundWorker bw = new BackgroundWorker(); bw.DoWork += new DoWorkEventHandler(bw_DoWork); bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); bw.RunWorkerAsync(); //backgroundWorker1.RunWorkerAsync(); } catch (Exception ex) { MessageBox.Show("Unable to process.\nError:" + ex.Message, Properties.Settings.Default.AppName); } } } void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { buttonRun.Enabled = true; pictureBox1.Visible = false; } void bw_DoWork(object sender, DoWorkEventArgs e) { u.Execute(); }

    Read the article

  • WPF/Silverlight AutoCompleteBox with ability to add new values to list.

    - by WillH
    Hi, I would like to use autocompletebox with a list of values, but also add new values to the list if a user enters one that isn't present. I currently have a string property in my view model called 'Comment'. Currently this is bound to a textbox in the view - user types a comment and the view model is updated. Simple. To save time, my customer would like it to autocomplete from previous values, so the way I thought to do this is something like: ViewModel public string Comment; public ObservableCollection<string> CommentsList { ... } (populate the CommentsList when the viewmodel is created) View <AutoCompleteComboBox ItemsSource="{Binding CommentsList}" SelectedItem="{Binding Comment, Mode=TwoWay/> So when the user selects a value, it saves the value in the Comment property. This works fine if the user selects an item in the list, but if the user types in a new value, the comment property is not updated (it is null because the selected item was not in the list). Is this possible with autocompletebox? Thanks in advance, Will

    Read the article

  • Silverlight 4 race condition with DataGrid master details control

    - by Simon_Weaver
    Basically I want a DataGrid (master) and details (textbox), where DataGrid is disabled during edit of details (forcing people to save/cancel)... Here's what I have... I have a DataGrid which serves as my master data. <data:DataGrid IsEnabled="{Binding CanLoad,ElementName=dsReminders}" ItemsSource="{Binding Data, ElementName=dsReminders}" > Its data comes from a DomainDataSource: <riaControls:DomainDataSource Name="dsReminders" AutoLoad="True" ... I have a bound Textbox which is the 'details' (very simple right now). There are buttons (Save/Cancel) which should be enabled when user tries to edit the text. Unfortunately Silverlight doesn't support UpdateSourceTrigger=PropertyChanged so I have to raise an event: <TextBox Text="{Binding SelectedItem.AcknowledgedNote, Mode=TwoWay, UpdateSourceTrigger=Explicit, ElementName=gridReminders}" TextChanged="txtAcknowledgedNote_TextChanged"/> The event to handle this calls BindingExpression.UpdateSource to update the source immediately: private void txtAcknowledgedNote_TextChanged(object sender, TextChangedEventArgs e) { BindingExpression be = txtAcknowledgedNote.GetBindingExpression(TextBox.TextProperty); be.UpdateSource(); } IN other words - typing in the textbox causes CanLoad of the DomainDataSource to become False (because we're editing). This in turn disables the DataGrid (IsEnabled is bound to it) and enables 'Cancel' and 'Save' buttons. However I'm running up against a race condition if I move quickly through rows in the DataGrid (just clicking random rows). The TextChanged presumably is being called on the textbox and confusing the DomainDataSource which then thinks there's been a change. So how should I disable the DataGrid while editing without having the race condition? One obvious solution would be to use KeyDown events to trigger the call to UpdateSource but I always hate having to do that.

    Read the article

  • Telerik Silverlight RadComboBox Selected Item

    - by Chirag
    i am customize telerik Datapager control in that control create one resource file and add one combobox for change page size of grid <UserControl.Resources> ....... <telerik:RadComboBox x:Name="CmbPageSize" MinWidth="40" telerik:StyleManager.Theme="{StaticResource Theme}" ItemsSource="{Binding Path=BindPageSize, Mode=TwoWay}" SelectedItem="{Binding Path=DataPagerPageSize_string, Mode=TwoWay}"></telerik:RadComboBox> ....... Bind a combo with public string DataPagerPageSize_string { get { if (_DataPagerPageSize_string == null || _DataPagerPageSize_string == string.Empty) { //DatapagerIndex = 1; return DefaultPageSize.ToString(); } return _DataPagerPageSize_string; } set { _DataPagerPageSize_string = value; OnPropertyChanged("_DataPagerPageSize_string"); } } public List<string> BindPageSize { get { List<string> Pagerdata = new List<string>(); Pagerdata.Add("10"); Pagerdata.Add("20"); Pagerdata.Add("50"); Pagerdata.Add("100"); Pagerdata.Add("250"); Pagerdata.Add("500"); Pagerdata.Add("750"); Pagerdata.Add("1000"); Pagerdata.Add("1500"); Pagerdata.Add("2000"); Pagerdata.Add("Automatic"); Pagerdata.Add("All"); return Pagerdata; } } this is working fine in case of if i select a value from combobox but i wan to change it from code behind Like EVP.DataPagerPageSize_string = "All"; this thigs works fine but Combobox display me a old value; if i will check a property then it show me a newly set value but combobox not select newly value

    Read the article

  • Can a WPF ComboBox display alternative text when its selection is null?

    - by Garth T Kidd
    G'day! I want my WPF ComboBox to display some alternative text when its data-bound selection is null. The view model has the expected properties: public ThingoSelectionViewModel : INotifyPropertyChanged { public ThingoSelectionViewModel(IProvideThingos) { this.Thingos = IProvideThingos.GetThingos(); } public ObservableCollection<Thingo> Thingos { get; set; } public Thingo SelectedThingo { get { return this.selectedThingo; } set { // set this.selectedThingo and raise the property change notification } // ... } The view has XAML binding to the view model in the expected way: <ComboBox x:Name="ComboboxDrive" SelectedItem="{Binding Path=SelectedThingo}" IsEditable="false" HorizontalAlignment="Left" MinWidth="100" IsReadOnly="false" Style="{StaticResource ComboboxStyle}" Grid.Column="1" Grid.Row="1" Margin="5" SelectedIndex="0"> <ComboBox.ItemsSource> <CompositeCollection> <ComboBoxItem IsEnabled="False">Select a thingo</ComboBoxItem> <CollectionContainer Collection="{Binding Source={StaticResource Thingos}}" /> </CompositeCollection> </ComboBox.ItemsSource> </ComboBox> The ComboBoxItem wedged into the top is a way to get an extra item at the top. It's pure chrome: the view model stays pure and simple. There's just one problem: the users want "Select a thingo" displayed whenever the ComboBox' selection is null. The users do not want a thingo selected by default. They want to see a message telling them to select a thingo. I'd like to avoid having to pollute the viewmodel with a ThingoWrapper class with a ToString method returning "Select a thingo" if its .ActualThingo property is null, wrapping each Thingo as I populate Thingos, and figuring out some way to prevent the user from selecting the nulled Thingo. Is there a way to display "Select a thingo" within the ComboBox' boundaries using pure XAML, or pure XAML and a few lines of code in the view's code-behind class?

    Read the article

  • Launch User Control in a tab control dynamically

    - by Redburn
    I have a custom built menu system in which I would like to load user controls from another project into a tab control on my main project (menu control) User control Project : foobar Menu system Project : Menu The function to load them into the tab control: private void LaunchWPFApplication(string header, string pPath) { // Header - What loads in the tabs header portion. // pPath - Page where to send the user //Create a new browser tab object BrowserTab bt = tabMain.SelectedItem as BrowserTab; bt = new BrowserTab(); bt.txtHeader.Text = header; bt.myParent = BrowserTabs; //Load in the path try { Type formType = Type.GetType(pPath, true); bt.Content = (UserControl)Activator.CreateInstance(formType); } catch { MessageBox.Show("The specified user control : " + pPath + " cannot be found"); } //Add the browser tab and then focus BrowserTabs.Add(bt); bt.IsSelected = true; } And what I send to the function as an example: LaunchWPFApplication("Calculater", "foobar.AppCalculater"); But every time run, the application complains that the formType is null. I am confused on how to load the user control and curious if I'm sending the correct parameters.

    Read the article

< Previous Page | 7 8 9 10 11 12 13 14 15  | Next Page >