2010-03-01 3 views
1

OnSourceInitialized 메서드를 재정 의하여 하나의 문제점이 있습니다. 내 콤보 상자에 C# 코드의 소스 속성을 채운 후 페이지가로드 될 때 (기본값) 콤보 상자에서 선택된 항목이 자동으로 나타나기를 원하지만 onsourceinitialized 메서드 후에 어떤 이유에서 콤보 상자가 항목 변경을 null로 선택했습니다.onsourceinitialized 후 wpf combobox selecteditem을 null로 변경했습니다.

EDIT 모든

첫째, 아주 좋은 설명 감사합니다.

더 자세히 설명하려고하고 다음 코드를 게시합니다. 나는 약간의 수정을했지만 성공하지는 못했다. 그것은 계속 작동하지 않습니다.

내 목표는 윈도우가로드되고 표시 될 때 콤보 상자에서 선택된 기본값을 표시하는 것입니다.

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 

편집 기본 사용자가 메뉴 응용 프로그램에서 옵션을 선택하면

처음에, 나는 다음을 수행 .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 및 텍스트 속성이 (내가 그것을 debbugged하고 정확했다)하지만 실행 후 올바른지 확인 점이다 OnSourceInitialized 메서드는 combobox의 selectedvalue 속성이 null 값을 가져옵니다.

또한 창이 열리면 콤보 박스가 기본 값으로 선택되지만 원하는 이유는 콤보 박스에서 비어있는 값으로 선택된다는 것입니다. 그것은 어떤 이벤트 (나는 디버깅을하고 null로 바뀌는 것을 보았 기 때문에 OnSourceMethod를 실행 한 후 생각합니다)는 combobox에서 ok로 나타나는 선택된 기본값을 비워 둡니다.

나는 comboboxes가 올바르게 채워지는지 테스트했다. 왜냐하면 일단 comboboxes를 클릭하면 그들이 채워진 것을 볼 수 있기 때문이다.

또한

내가 수행하여 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 (즉, 선택한 항목 설정)를 호출하여이 문제를 해결할 수 있습니다. DataContext에서 "ID"속성이 SelectedItem가 null로 설정됩니다 ItemsSource의 항목이 아닌 경우

SelectedItem="{Binding Path=Id}" 

:

3

원인

이 문제가 될 것으로 보인다.

타이밍InitializeComponent가 호출

, 그 바인딩을 설정 SelectedItem XAML를 파싱한다. DataContext이 설정되어 있지 않은 경우, 초기에는 null이됩니다. 나중에 DataContext이 설정되면 바인딩이 다시 평가됩니다. 이 시점에 Id이 목록에 있으면 SelectedItem이 설정됩니다. 그렇지 않은 경우는 null로 설정됩니다.

InitializeComponent 동안 처음에는 평가할 수없는 모든 바인딩은 모든 이벤트가 발생하면 재전송을 위해 디스패처를 사용하여 예약됩니다. DataContext 설정 방법에 대한 세부 사항없이 구체화 할 수는 없지만 바인더 중 하나가 지연되어 있으므로 {Binding Path=Id} 바인딩이 디스패처 콜백에서 평가됩니다.

Dispatcher 콜백은 이벤트가 아니며 우선 순위가 설정된 작업 대기열입니다. 그들이

  • 사용하십시오 Dispather.BeginInvoke이 바인딩 후 실행 자신의 콜백 일정을 초기화하는 동안 평가 될 수 있도록

    1. 변경 바인딩은
    2. 하자를 완료 : 당신은 상황의이 종류가 있다면 당신의 선택은

    추가 참고

    을 selectedItem을 설정하는 대신 코드를 수동으로 설정하는 바인딩 돌봐

    SelectedValueSource을 사용하면 의심스러운 것으로 보입니다. 귀하의 SelectedItem 바인딩은 ItemsSource의 각 항목은 "ID"을 나타 내기 위해 보이지만 SelectedValueSource의 당신의 정의는 ItemsSource의 각 항목은 "ID" 포함되어 있음을 나타내는 것으로 보인다. 다른 구조에 의해 구조 자체가 "Id"라고 불리는 데이터 구조를 찾는 것은 드문 일이지만 "Id"필드가 있습니다. 따라서 나는 여기에 약간의 혼란을 의심한다. 실제 데이터 구조를 보지 않으면 더 말할 수 없습니다.

    OnSourceInitialized을 사용하면 오해가있는 것처럼 보입니다. OnSourceInitialized이라는 이름의 "원본"은 데이터 소스가 아닌 Win32 헤더와 같은 "프레젠테이션 원본"을 나타냅니다. OnSourceInitialized의 목적은 Windows 운영 체제와 낮은 수준에서 상호 작용하거나 응용 프로그램이 제공되는 위치를 기반으로 응용 프로그램을 업데이트하는 것입니다.당신의 사용은 이것과 전혀 무관 한 것처럼 보입니다. OnSourceInitialized에서 멀리 떨어져있는 것이 좋습니다. 일반적으로 ComboBoxes 등을 초기화하는 가장 좋은시기는보기 모델에서 제공하고 데이터 바인딩으로 처리하는 것입니다. 뷰 모델이 사용 가능 해지면 코드없이 데이터가 채워집니다.

  • 0

    나는 그것을 풀었다!

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

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

    용액을 변경하는 것이다

    문제 EditPreferences.xaml에서 selectedItem가 등록 결합에 참여