首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >已初始化后,wpf组合框选择项目为null

已初始化后,wpf组合框选择项目为null
EN

Stack Overflow用户
提问于 2010-03-01 11:53:10
回答 4查看 5.9K关注 0票数 1

我高估了OnSourceInitialized方法,我有一个问题。在使用c#代码中的源属性填充combobox之后,在加载页(默认值)时,将自动在组合框中显示选中的项,但由于某种原因,在进行onsourceinitialized方法之后,组合框选定的项将更改为null。

编辑

首先,非常好的解释谢谢。

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

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

最初,当用户在菜单应用程序中选择一个选项时,我执行以下操作:

WinMain.xaml.cs:

代码语言:javascript
运行
复制
    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:

代码语言:javascript
运行
复制
           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 (我举一个组合框为例):

代码语言:javascript
运行
复制
            <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:

代码语言:javascript
运行
复制
             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被执行时,combobox的selectedvalue和text属性都是正确的(我已经对它进行了调试,并且是正确的),但是在执行OnSourceInitialized方法之后,combobox的selectedvalue属性将获得null值。

我还注意到,当窗口打开时,组合框会出现,并选择我想要的默认值,但我很快就会看到,由于某些原因,它们的值在组合框中变为空值。这类似于一些事件(我认为是在执行OnSourceMethod之后,因为我已经调试并查看了它如何更改为null),使在组合框中显示为ok的选定默认值变为空。

我已经测试了comboboxes的正确填充,因为一旦显示了窗口,我就在组合框中单击,我可以看到它们被填充了。

编辑2

此外,我还强制在fillControls方法中为combobox选择索引,方法如下:

代码语言:javascript
运行
复制
cbLimHorasExtra.SelectedIndex = 1;

但没有成功..。

combobox中填充了值:0到8,两者都包括在内。

EN

回答 4

Stack Overflow用户

发布于 2010-03-01 18:17:19

这似乎就是问题所在:

代码语言:javascript
运行
复制
SelectedItem="{Binding Path=Id}" 

如果DataContext中的"Id“属性不是ItemsSource中的项,则SelectedItem将设置为null。

定时

当调用InitializeComponent时,它解析设置SelectedItem绑定的XAML。如果没有设置DataContext,那么最初它将为null。稍后,当设置DataContext时,重新计算绑定。如果此时Id在列表中,则设置SelectedItem。否则,它将设置为空。

任何在InitializeComponent期间无法最初评估的绑定都会使用dispatcher进行调度,一旦所有事件触发,将重新评估这些绑定。如果没有关于如何设置DataContext的详细信息,我无法给出具体的内容,但我的猜测是,您的一个绑定正在被推迟,因此您的{Binding Path=Id}绑定将在dispatcher回调中进行评估。

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

修改绑定,以便在initialization

  • Use a Dispather.BeginInvoke期间对绑定进行评估,以安排您自己的回调在绑定completes

  • Let之后执行,绑定负责设置SelectedItem,而不是在代码

中手动设置。

附加备注

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

您对OnSourceInitialized的使用也会使您看起来有一个误会。OnSourceInitialized名称中的" source“指的是”表示源“,如Win32 hWnd,而不是数据源。OnSourceInitialized的目的是与Windows操作系统进行低级别的交互,或者根据应用程序的出现位置更新应用程序。你的使用似乎与此完全无关。我建议你离OnSourceInitialized远点。通常,初始化ComboBoxes的最佳时机就是在视图模型中提供它,并让数据绑定来处理它。一旦视图模型可用,数据将被填充,不需要任何代码。

票数 3
EN

Stack Overflow用户

发布于 2010-03-01 12:01:07

在覆盖结束时设置SelectedIndex属性,顺便说一句,我似乎找不到OnSourceInitialised,只是初始化了。但是,如果您在代码的末尾设置了它,那么它仍然可以工作。

代码语言:javascript
运行
复制
    private void MyListBox_Initialized(object sender, EventArgs e)
    {
        // Run some code
        if (MyListBox.Items.Count > 0)
        {
            MyListBox.SelectedIndex = 0;
        }
    }
票数 0
EN

Stack Overflow用户

发布于 2010-03-01 13:56:59

对于您的问题,我没有一个真正的答案,但是OnSourceInitialized在初始化过程中似乎还为时过早。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2355531

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档