Search code examples
c#mvvmcomboboxuwptemplate10

Why cant I update ComboBox display when triggering another control event?


I'm developing an app and I'm using Template 10 and MVVM pattern for databing purposes, anyways

I have a DatePicker and a combobox, when ever I set the combobox via a contructor or a navigating to a page event the combobox gets set and display the value is set.

My combobox is use to set fortnight (24 different choices) so i wanted to add the event that whenever I changed the datepicker event i automatically sets the fortnight at the combobox displaying the proper fortnight accordingly to the date chosen.

But when ever i set a new date my combobox get blank or a empty value, displaying nothing, my converter register the conversion of my enum to an int value, but it isnt shown at my combo box this is my xaml for my controls:

<DatePicker x:Name="PaymentDateSeniorityInfoDatePicker"
                                    Date="{Binding PaymentDate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource DateToDatePickerConverter}}"
                                    DateChanged="{x:Bind ViewModel.PaymentDateChanged}"
                                    IsEnabled="{x:Bind ViewModel.ControlEnabled, Mode=OneWay, FallbackValue='true'}"/>

<ComboBox x:Name="FortnightNumberSeniorityBonusInfoComboBox"
                                  ItemsSource="{x:Bind ViewModel.Fortnights, Mode=OneWay}"
                                  SelectedValuePath="Value"
                                  DisplayMemberPath="Display"
                                  SelectedValue="{Binding FortnightNumber, Mode=TwoWay, Converter={StaticResource EnumItemsConverter}}"
                                  SelectedIndex="{Binding FortnightNumber, Mode=OneWay, Converter={StaticResource EnumItemsConverter}}"
                                  IsEnabled="{x:Bind ViewModel.ControlEnabled, Mode=OneWay}"/>

this is the logic event that set my combobox when ever i navigate to the page

public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> state)
{
    ShowAndHideButtons();
    AreAdsCollapsed = AdsCollapsed();
    LoadSeniorityBonusInfo();//This method set my fortnights
    await ExecutedRefreshedAsync();
    await base.OnNavigatedToAsync(parameter, mode, state);
}

void LoadSeniorityBonusInfo()
{
    SeniorityBonusInfo.FortnightNumber = GetFortnight(SeniorityBonusInfo.PaymentDate.Value);
    SeniorityBonusInfo.DaysOfSalary = GetDaysOfSalary(LaborInfo, PersonalInfo);
    SeniorityBonusInfo.SeniorityBonusPayment = CalculateSenorityBonus(SeniorityBonusInfo.DaysOfSalary, SeniorityBonusInfo.CurrentBasicSalary);
}

this is the event to set my new fortnight:

public void PaymentDateChanged()
{
    SeniorityBonusInfo.FortnightNumber = GetFortnight(SeniorityBonusInfo.PaymentDate.Value);
}

and finally this is my enum converter:

public class EnumItemsConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        if (!value.GetType().GetTypeInfo().IsEnum)
            return false;

        var enumName = value.GetType();
        var obj = Enum.Parse(enumName, value.ToString());

        return System.Convert.ToInt32(obj);
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        var enumType = (value as Enum).GetType();
        return Enum.ToObject(enumType, System.Convert.ToInt32(value));
    }
}

Can somebody help me out with this one, what am i forgetting or letting skip in order to update a control such as a combobox when setting another control.

It works with textblock without a problem, but in this case it isnt working.

I appreciate some guidance thanks!!!

UPDATE

I'm adding the classes that a fellow asked me.

ValidatableModelBase is a class from Template10.Validation library developed by Jerry Nixon is a github project and you can add it to your project via github.

as for BonusDays and Fortnight are just enums, this are my enums:

public enum BonusDays : Int32
{
    [Display(Name = "EnumBonusDays0")]
    BonusDays0 = 0,
    [Display(Name = "EnumBonusDays18")]
    BonusDays18 = 1,
    [Display(Name = "EnumBonusDays33")]
    BonusDays33 = 2,
    [Display(Name = "EnumBonusDays48")]
    BonusDays48 = 3,
    [Display(Name = "EnumBonusDays63")]
    BonusDays63 = 4,
    [Display(Name = "EnumBonusDays93")]
    BonusDays93 = 5,
    [Display(Name = "EnumBonusDays108")]
    BonusDays108 = 6
}

public enum Fortnight : Int32
{
    [Display(Name = "EnumFortnightQ00")]
    Q00 = 0,
    [Display(Name = "EnumFortnightQ01")]
    Q01 = 1,
    [Display(Name = "EnumFortnightQ02")]
    Q02 = 2,
    [Display(Name = "EnumFortnightQ03")]
    Q03 = 3,
    [Display(Name = "EnumFortnightQ04")]
    Q04 = 4,
    [Display(Name = "EnumFortnightQ05")]
    Q05 = 5,
    [Display(Name = "EnumFortnightQ06")]
    Q06 = 6,
    [Display(Name = "EnumFortnightQ07")]
    Q07 = 7,
    [Display(Name = "EnumFortnightQ08")]
    Q08 = 8,
    [Display(Name = "EnumFortnightQ09")]
    Q09 = 9,
    [Display(Name = "EnumFortnightQ10")]
    Q10 = 10,
    [Display(Name = "EnumFortnightQ11")]
    Q11 = 11,
    [Display(Name = "EnumFortnightQ12")]
    Q12 = 12,
    [Display(Name = "EnumFortnightQ13")]
    Q13 = 13,
    [Display(Name = "EnumFortnightQ14")]
    Q14 = 14,
    [Display(Name = "EnumFortnightQ15")]
    Q15 = 15,
    [Display(Name = "EnumFortnightQ16")]
    Q16 = 16,
    [Display(Name = "EnumFortnightQ17")]
    Q17 = 17,
    [Display(Name = "EnumFortnightQ18")]
    Q18 = 18,
    [Display(Name = "EnumFortnightQ19")]
    Q19 = 19,
    [Display(Name = "EnumFortnightQ20")]
    Q20 = 20,
    [Display(Name = "EnumFortnightQ21")]
    Q21 = 21,
    [Display(Name = "EnumFortnightQ22")]
    Q22 = 22,
    [Display(Name = "EnumFortnightQ23")]
    Q23 = 23,
    [Display(Name = "EnumFortnightQ24")]
    Q24 = 24
}

I'm using the Display atribute to localize the display value from english to spanish and viceversa!!!

this is my valuedispl;ay class to help me with localizing:

public class ValueDisplay
{
    public Enum Value { get; set; }
    public string Display { get; set; }
}

this is my enum extension to help me with localization:

public static class EnumExtensions
{
    public static string Display(this Enum eValue)
    {
        var nAttributes = eValue.GetType().GetField(eValue.ToString()).GetCustomAttributes(typeof(DisplayAttribute), false);
        var DisplayName = string.Empty;
        if (nAttributes.Any())
        {
            DisplayName = GetLocalizeString((nAttributes.FirstOrDefault() as DisplayAttribute).Name);
            return DisplayName;
        }
        else
        {
            throw new ArgumentException("No hay Attributo asignado para el Enum");
        }
    }
}

and finally this is my localize string class

public static class LocalizeService
{
    public static string GetLocalizeString(string varName)
    {
        return App.Loader.GetString(varName);
    }
}

hopefully this gives you enough information, thanks for your interest!


Solution

  • I solve it, but I had to use conventional events and leave a side my viewmodel x:bind methods. I just put an event at datepicker at DateChanged event and set the combobox index in code behind. this is my xaml and code behind code.

    I didnt like the solution but since I dont want to stop here just for that it'll work while I find out how to solve it entirely using MVVM pattern.

    hopefully somebody has a better solution than me.

    this is my code:

    XAML:

    <DatePicker x:Name="PaymentDateSeniorityInfoDatePicker"
                                        Date="{Binding PaymentDate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource DateToDatePickerConverter}}"
                                        DateChanged="PaymentDateSeniorityInfoDatePicker_DateChanged"
                                        IsEnabled="{x:Bind ViewModel.ControlEnabled, Mode=OneWay, FallbackValue='true'}"/>
    

    ViewModel:

    public void PaymentDateChanged()
        {
            SeniorityBonusInfo.FortnightNumber = GetFortnight(SeniorityBonusInfo.PaymentDate.Value);
        }
    
    public SeniorityBonusDTO SeniorityBonusInfo
        {
            get { return _SeniorityBonusInfo; }
            set { Set(ref _SeniorityBonusInfo, value); }
        }
    

    my DTO Model:

     public class SeniorityBonusDTO : ValidatableModelBase
     {
        [Required]
        public DateTime? PaymentDate
        {
            get { return Read<DateTime?>(); }
            set { Write(value, nameof(PaymentDate), false); }
        }
    
        [Required]
        public decimal? CurrentBasicSalary
        {
            get { return Read<decimal?>(); }
            set { Write(value, nameof(CurrentBasicSalary), false); }
        }
    
        [Required]
        public BonusDays DaysOfSalary
        {
            get { return Read<BonusDays>(); }
            set { Write(value, nameof(DaysOfSalary), false); }
        }
    
        [Required]
        public Fortnight FortnightNumber
        {
            get { return Read<Fortnight>(); }
            set { Write(value, nameof(FortnightNumber), false); }
        }
    
        [Required]
        public decimal? SeniorityBonusPayment
        {
            get { return Read<decimal?>(); }
            set { Write(value, nameof(SeniorityBonusPayment), false); }
        }
    }
    

    and my code behind:

    private void PaymentDateSeniorityInfoDatePicker_DateChanged(object sender, DatePickerValueChangedEventArgs e)
        {            
            ViewModel.PaymentDateChanged();
            FortnightNumberSeniorityBonusInfoComboBox.SelectedIndex = (int)ViewModel.SeniorityBonusInfo.FortnightNumber;
        }
    

    please if somebody has a better idea, I would appreciate your help, Thanks!!!