2010-03-01 104 views
1

我已经重写了OnSourceInitialized方法,并且有一个问题。在用c#代码中的源属性填充我的组合框之后,我想自动地在加载页面时默认出现在组合框中的项目(默认值),但是在onsourceinitialized方法之后,组合框选定项目更改为空。wpf combobox selecteditem在初始化初始化后为空

编辑

首先,解释感谢非常好。

我会尝试解释更多,我会发布一些代码如下。我做了一些修改,但没有成功。它继续不起作用。

我的目标是显示窗口加载并显示时在组合框中选择的默认值。

最初,当用户选择的菜单应用程序中的选项我做到以下几点:

WinMain.xaml.cs:

namespace MyNamespace 
    { 

     public partial class WinMain : Window 
     { 

      <...> 

      private void mnuItemPreferences_Click(object sender, RoutedEventArgs e) 
      { 

      MyNamespace.Windows.EditPreferences editPrefWnd = 
        new MyNamesapece.Windows.EditPreferences(); 

      // 
      // Modal window that I want to open with default values in comboboxes 
      // 
      editPrefWnd.ShowDialog(); 
      } 

      <...> 

     } // end WinMain class 
     } // end namespace 

EditPreferences.xaml.cs:

  namespace MyNamespace.Windows 
      { 
       public partial class EditPreferences : Window 
       { 
       <...> 

       // My constructor 
       public EditPreferences() 
     { 
        // 
        // Handlers 
        // 
        Loaded += PreferencesWindow_Loaded; 
        Closing += PreferencesWindow_Closing; 

     InitializeComponent(); 

     if (System.Environment.OSVersion.Version.Major < 6) 
        { 
      this.AllowsTransparency = true; 
      _bolAeroGlassEnabled = false; 
     } 

     else 
        { 
      _bolAeroGlassEnabled = true; 
     } 

        this.ShowInTaskbar = false; 

       } // end constructor 

     private void PreferencesWindow_Loaded(object sender, 
                System.Windows.RoutedEventArgs e) 
     { 

        if (this.ResizeMode != System.Windows.ResizeMode.NoResize) 
        { 
        //this work around is necessary when glass is enabled and the 
        //window style is None which removes the chrome because the 
        //resize mode MUST be set to CanResize or else glass won't display 

        this.MinHeight = this.ActualHeight; 
        this.MaxHeight = this.ActualHeight; 

        this.MinWidth = this.ActualWidth; 
        this.MaxWidth = this.ActualWidth; 
        } 


        // 
        // Populate comboboxes 
        // 
        cbLimHorasExtra.ItemsSource = Accessor.GetLimHorasExtraSorted(); 
        cbFracHorasExtra.ItemsSource = Accessor.GetFracHorasExtraSorted(); 

        // 
        // Fill controls with default values (see below) 
        // 
        FillControls(); 

        // 
        // Install other handlers 
        // 
        rdoBtnOTE.Checked += this.rdoBtnOTE_Checked; 
        rdoBtnOTM.Checked += this.rdoBtnOTM_Checked; 
        chkboxRestrict.Checked += this.chkboxRestrict_Checked; 
        expAdditionalDetails.Collapsed += 
            this.expAdditionalDetails_Collapsed; 
        expAdditionalDetails.Expanded += this.expAdditionalDetails_Expanded; 
        cbLimHorasExtra.SelectionChanged += 
         this.cbLimHorasExtra_SelectionChanged; 
        cbFracHorasExtra.SelectionChanged += 
         this.cbFracHorasExtra_SelectionChanged; 
       } 

       protected override void OnSourceInitialized(System.EventArgs e) 
       { 

        base.OnSourceInitialized(e); 

        if (_bolAeroGlassEnabled == false) 
        { 
         //no aero glass 
         this.borderCustomDialog.Background = 
           System.Windows.SystemColors.ActiveCaptionBrush; 
         this.tbCaption.Foreground = 
           System.Windows.SystemColors.ActiveCaptionTextBrush; 
         this.borderCustomDialog.CornerRadius = 
           new CornerRadius(10, 10, 0, 0); 
         this.borderCustomDialog.Padding = 
           new Thickness(4, 0, 4, 4); 
         this.borderCustomDialog.BorderThickness = 
           new Thickness(0, 0, 1, 1); 
         this.borderCustomDialog.BorderBrush = 
           System.Windows.Media.Brushes.Black; 
         } 
         else 
         { 
         //aero glass 
         if (VistaAeroAPI.ExtendGlassFrame(this, 
           new Thickness(0, 25, 0, 0)) == false) 
         { 
          //aero didn't work make window without glass 
          this.borderCustomDialog.Background = 
           System.Windows.SystemColors.ActiveCaptionBrush; 
          this.tbCaption.Foreground = 
           System.Windows.SystemColors.ActiveCaptionTextBrush; 
          this.borderCustomDialog.Padding = 
           new Thickness(4, 0, 4, 4); 
          this.borderCustomDialog.BorderThickness = 
           new Thickness(0, 0, 1, 1); 
          this.borderCustomDialog.BorderBrush = 
           System.Windows.Media.Brushes.Black; 

          _bolAeroGlassEnabled = false; 
         } 
         } 
       } 

       private void FillControls() 
       { 
        tblPreferencias tbl_pref = null; 

        // 
        // Obtain data (a record with fields) 
        // Accessor is a class where I define the methods to 
        // obtain data of different tables in my database 
        // 
        tbl_pref = Accessor.GetActualPreferencias(); 

        // 
        // Only returns one register 
        // 
        if (tbl_pref != null) 
        { 
         rdoBtnOTE.IsChecked = (bool)tbl_pref.OTE; 
         rdoBtnOTM.IsChecked = (bool)tbl_pref.OTM; 
         chkboxRestrict.IsChecked = 
               (bool)tbl_pref.RestriccionHExtraTipoA; 

         // Here the value assigned is always in the range of the values 
         // which combo has been populated. 
         // With one 0 ... 8 
         // I debbugged it and works. 
         // selected value (no null) and text gets the correct value I 
         // want but after OnSourceInitialized method is executed I note 
         // that for some rease selected value property gets value null 
         cbLimHorasExtra.Text = tbl_pref.LimiteHorasExtra.ToString(); 
         cbFracHorasExtra.Text = 
             tbl_pref.FraccionDeMinutosExtra.ToString(); 
        } 
       } 

       <...> 
       } // end EditPreferences class 
      } // end namespace 

EditPreferences .xaml(我把它当成组合框的一个例子):

  <Window x:Class="MyNamespace.Windows.EditPreferences" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      Title="EditPreferences" Height="Auto" Width="500" 
      Background="{x:Null}" 
      SnapsToDevicePixels="True" SizeToContent="Height" 
      WindowStartupLocation="CenterScreen" 
      ResizeMode="NoResize" 
      WindowStyle="None" 
      Margin="0,0,0,0" 
      > 

      <...> 

      <ComboBox x:Name="cbLimHorasExtra" 
         DisplayMemberPath="LimHora" 
         SelectedValuePath="Id" 
         SelectedItem="{Binding Path=Id}" 
         VerticalAlignment="Center" 
         HorizontalContentAlignment="Right" 
         Width="50"/> 

      <...> 
      </Window> 

Accessor.cs:

   namespace GesHoras.Classes 
      { 

       class Accessor 
       { 
       <...> 

       // This method is used to populate the combobox with its values 
       // tblLimHorasExtra is a table in my SQL Database 
       // Its fields are: 
       // 
       // Id : int no null (numbers 1 ... 9) 
       // LimHora: int no null (numbers 0 ... 8) 
       // 
       public static System.Collections.IEnumerable GetLimHorasExtraSorted() 
       { 
        DataClassesBBDDDataContext dc = new 
                DataClassesBBDDDataContext(); 

        return (from l in dc.GetTable<tblLimHorasExtra>() 
          orderby l.LimHora 
          select new { Id=l.Id, LimHora=l.LimHora }); 
       } 

       // tblPreferencias is a table in my SQL Database 
       // Its fields are: 
       // 
       // Id : int no null 
       // Descripcion : varchar(50) no null 
       // OTE : bit no null 
       // OTM : bit no null 
       // LimiteHorasExtra : int no null 
       // FraccionDeMinutosExtra : int no null 
       // RestriccionHExtraTipoA : bit no null 
       // 
       public static tblPreferencias GetActualPreferencias() 
       { 
        DataClassesBBDDDataContext dc = new 
                DataClassesBBDDDataContext(); 

        return (from actP in dc.GetTable<tblPreferencias>() 
          where (actP.Id == 3) 
          select actP).SingleOrDefault<tblPreferencias>(); 
       } 
       <...> 

      } // end class 
      } // end namespace 

我看到的问题是,当执行方法fillControls一切正常,和的SelectedValue text属性的组合框是正确的(我debbugged它,是正确的),但执行后OnSourceInitialized方法中,combobox的selectedvalue属性获取null值。

而且我注意到,窗口打开时,该组合框显示与选择,我想,但很快我看到,由于某种原因,他们的价值观选择轮流在组合框为空的默认值。这就像一些事件(我认为在执行OnSourceMethod之后,因为我已经调试过,并且看到它是如何变为null的),使得在组合框中看起来好的默认值变为空。

我已经测试了组合框无误,因为一旦所示的窗口,我的组合框点击,我可以看到他们填充好。

EDIT 2

而且我已经做被迫在fillControls方法组合框中选择指标:

cbLimHorasExtra.SelectedIndex = 1; 

但没有成功......

组合框填充值:包括0到8。

回答

0

在覆盖的最后设置SelectedIndex属性,顺便说一句,我似乎无法找到OnSourceInitialised,只有初始化。但是如果你将它设置在你的代码的最后,它应该仍然可以工作。

private void MyListBox_Initialized(object sender, EventArgs e) 
    { 
     // Run some code 
     if (MyListBox.Items.Count > 0) 
     { 
      MyListBox.SelectedIndex = 0; 
     } 
    } 
0

我没有真正回答你的问题,但OnSourceInitialized似乎是在初始化过程中过早。

同样,我还没有尝试过您的确切场景,但像这样的许多问题可以通过在Loaded事件中调用FillControls(即设置所选项)来解决,而不是在早期。

3

原因

这似乎是这个问题:

SelectedItem="{Binding Path=Id}" 

如果DataContext的 “ID” 属性是不是在的ItemsSource的项目,SelectedItem将被设置为null。

时序

InitializeComponent被调用时,它分析该设置SelectedItem结合XAML。如果DataContext未设置,则最初这将为空。稍后当设置DataContext时,绑定将被重新评估。如果Id在该列表中,则设置SelectedItem。否则它被设置为空。

InitializeComponent期间最初无法评估的任何绑定都是使用调度程序计划的,一旦所有事件触发后都将重新评估该调度程序。如果没有关于如何设置DataContext的详细信息,我不能提供具体信息,但我的猜测是您的某个绑定正在延迟,因此您的调用器回调中将评估您的绑定。

调度程序回调不是一个事件 - 它是一个优先级的工作队列。如果你有这种情况你的选择是:

  1. 更改绑定,使他们能够初始化
  2. 使用Dispather.BeginInvoke来安排自己的回调绑定后执行过程中进行评估完成
  3. 设绑定照顾设置selectedItem而不是代码手动设置

其他备注

您使用SelectedValueSource看起来很可疑。您对SelectedItem结合似乎表明,在ItemsSource每个产品的“身份证”,但你的SelectedValueSource定义似乎表明,在ItemsSource每个项目包含的“身份证”。很难找到一个数据结构,其中结构本身被另一个结构称为“Id”,但它本身有一个“Id”字段。因此我怀疑这里有些混乱。没有看到你的实际数据结构,我不能再多说了。

您对OnSourceInitialized的使用也会导致您的误解。名称为OnSourceInitialized的“源”是指“演示源”,例如Win32 hWnd,而不是数据源。 OnSourceInitialized的目的是与Windows操作系统进行低级别的交互,或者根据它的呈现位置更新您的应用程序。你的使用似乎与此无关。我会建议你远离OnSourceInitialized。一般来说,初始化ComboBoxes的最佳时间就是在视图模型中提供它,并让数据绑定来处理它。只要视图模型可用,数据将被填充,不需要代码。

0

我已经解决了!

的问题是在结合在EditPreferences.xaml SelectedItem属性:

  <ComboBox x:Name="cbLimHorasExtra" 
        DisplayMemberPath="LimHora" 
        SelectedValuePath="Id" 
        SelectedItem="{Binding Path=Id}" 
        VerticalAlignment="Center" 
        HorizontalContentAlignment="Right" 
        Width="50"/> 

的解决方案是改变为:

  <ComboBox x:Name="cbLimHorasExtra" 
        DisplayMemberPath="LimHora" 
        SelectedValuePath="Id" 
        SelectedItem="Id" 
        VerticalAlignment="Center" 
        HorizontalContentAlignment="Right" 
        Width="50"/>