2017-03-10 2 views
0

이것은 오랜 시간 lurker이지만이 포럼의 첫 번째 게시물입니다. 저는 약 2 개월 정도 WPF를 배우기 시작했으며, 훈련 목적으로 응용 프로그램을 만들려고합니다.WPF : DataGrid에 대한 데이터 바인딩

EF6 ORM을 사용하여 응용 프로그램에 추가 한 백엔드 데이터베이스가 있습니다. 내 응용 프로그램에서는 데이터베이스의 테이블에있는 열에 채워야하는 ComboBox가 있습니다. 목록에 바인딩을 사용하면됩니다.

문제가있는 부분은 DataGrid입니다. DataGrid의 열은 ComboBox에서 선택한 Item에 따라 채워 져야합니다.

내 데이터베이스 :

Here is my database structure

당신이 볼 수 있듯이, 학교가 여러 부서를 가지고 있으며, 그 부서의 각각 HOD와 학생의 강도를 가지고있다.

내 응용 프로그램 :

Here is the snapshot of the app

ComboBox는 학교 이름으로 채워집니다. DataGrid은 학교 이름이 선택되면 채워집니다. DataGrid에는 학교에서 사용할 수있는 부서별로 각 행이 있습니다. 그래서 해당 칼럼을 해당 학교의학과와 묶어야합니다. 그렇게 많이. 그러나 사용자가 입력 한 의견을 피드백 TextBox에 저장하고 싶습니다.

DataGrid을 개체에 바인딩 할 수 있도록 클래스를 만드는 방법을 이해할 수 없습니다. DataGrid을 개체에 바인딩 한 다음 해당 열을 다른 개체에 개별적으로 바인딩 할 수 있습니까? 이 작업은 데이터 그리드에 바인딩하도록되어

:

편집 데이터베이스에서 생성 된 기관에서 별도로

, 나는 두 개의 클래스가 있습니다. 그리고 FeedbackLine은 다음과 같습니다 :

public class FeedbackLine: INotifyPropertyChanged 
{ 
    private string _dept; 

    public string Department 
    { 
     get { return _dept; } 
     set { _dept = value; 
      OnPropertyChanged("Department"); 
     } 
    } 

    private string _HOD; 

    public string HOD 
    { 
     get { return _HOD; } 
     set { _HOD = value; 
      OnPropertyChanged("HOD"); 
     } 
    } 

    private int _strength; 

    public int Strength 
    { 
     get { return _strength; } 
     set { _strength = value; 
      OnPropertyChanged("Strength"); 
     } 
    } 

    private bool _isSelected; 

    public bool Selected 
    { 
     get { return _isSelected; } 
     set { _isSelected = value; 
      OnPropertyChanged("Selected"); 
     } 
    } 

    private string _comment; 

    public string Comment 
    { 
     get { return _comment; } 
     set { _comment = value; 
      OnPropertyChanged("Comment"); 
     } 
    } 

    private void OnPropertyChanged(string v) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(v)); 
    } 



    public event PropertyChangedEventHandler PropertyChanged; 
} 

나는 ViewModel을 사용하지 않았습니다. 문제는 LINQ에별로 좋지 않습니다. 클래스와 객체가 너무 많아서 어느 클래스를 바인딩해야할지 모릅니다. 내가 얻을 수있는 유일한 모호한 아이디어는 선택한 School을 사용하여 데이터베이스를 쿼리하기 위해 LINQ를 사용하고 FeedbackLines을 채워야한다는 것입니다.

편집 2 : 관심있는 사람들을위한 , 여기 내 모델 다이어그램은 WPF에서의 : Model Diagram

편집 3 : 은 내가 ViewModel에 대한 혼란 스러워요 생각합니다. 화면에 표시 될 데이터가 반드시 저장할 데이터는 아닙니다. 예를 들어, 선택되지 않은 행은 저장하지 않으려합니다. 내 Feedback 클래스는 데이터를 표시하고 저장하려고 시도합니다. 그리고 거기에 문제가 있습니다.DataGrid은 객체에 바인딩 될 수 있지만 열은 다른 객체에 바인딩되지 않습니까? 예를 들어 Department에 Combobox을 사용하도록 선택했다면 그런 다음 항목을 표시하는 데 ItemsSource을 사용해야하지만 SelectedItem 만 저장해야합니다. 나는이 두 가지 관심사를 분리 할 길을 찾을 수 없다.

+2

코드를 공유 할 수 있습니까? –

+0

코드를 게시하십시오. –

+0

코드에 따라 뷰 모델 또는 xaml을 의미합니까? –

답변

0

나는 데이터의 ViewModel가 데이터베이스에 연결되지 않은 경우가 더 나은 아키텍처의 피드백 생성자

public Feedback(string school, List<FeedbackLine> feedbackLines) 
{ 
    School = school; 
    FeedbackLines = new ObservableColleytion<FeedbackLine>(feedbackLines); 
} 

변경합니다. 당신은 당신의 선택을 별도의 수업에 넣을 수 있습니다.

LINQ 성명서에 도움이 필요하면 도와 드리겠습니다. 당신이 당신의 데이터는 제가 위에서 보여 새로운 생성자에 추가 할 FeedbackLines의 인스턴스를 만들 수 왔을 때 당신의 피드백 생성자에서

당신은

//but then what? 

을 썼다.

당신이 다른 viewmodels에서 그것을처럼 당신이 (당신의보기의 DataContext이다)이 당신의 ViewModel가에서 INotifyPropertyChanged와 함께

public void ObservableCollection<Feedback> Feedbacks 

을 필요로 않았다

.

xaml에는 학교와 ComboBox가 있습니다. 해당 콤보 박스에 이름을 지정하십시오 (예 : SchoolsComboBox. 당신은 익명의 유형을 만들어 하여 데이터 그리드에서 는 LINQ를 추가하는 동안이 줄을

Source={Binding ElementName=SchoolsComboBox, Path=SelectedItem.FeedbackLines} 

/편집 물품. 그냥 대신 FeedbackLine을 만들면 괜찮습니다.

var feedbackLines = Context.Schools.Where(c => c.SchoolName == school) 
            .Select(c => new FeedbackLine 
              { 
               Department = c.AvailableDepts.Dept, 
               HOD = c.AvailableDepts.HeadOfDept, 
               Strength = c.AvailableDepts.StudentStrength} 
            .ToList() 
+0

설명해 주셔서 감사합니다. 건축을 훨씬 청결하게 만들었습니다. LINQ에 관해서, 나는 아직도 붙어있다. 나는 같은 것을 사용하고있다. var FeedbackLines = Context.Schools.Where (c => c.SchoolName == school) .Select (c => new {Department = c.AvailableDepts.Dept, HOD = c.AvailableDepts.HeadOfDept, Strength = c.AvailableDepts.StudentStrength} .ToList()'그러나 익명 객체의 IEnumerable을 반환합니다. 어떻게 이것을 FeedbackLines에 캐스트해야합니까? –

+0

내 대답을 편집하고 LINQ 문을 추가했습니다. 작동한다면 행복 할 것입니다. upvote 및 내 대답을 받아 들일 때 :) –

+0

upvote 않았다,하지만 내 평판을 나던 공개 할 수 있습니다. 죄송합니다. LINQ에 감사드립니다. 그것은 작동합니다, 적어도 단순한 수표는 그것을 보여 줬습니다. –

0

U 이렇게 할 수 있습니다. 확실하게 글을 쓸 수는 있지만 작동합니다. 당신의 ViewModel에서

가에서 INotifyPropertyChanged 당신이 당신의 콤보 상자에 바인딩 컬렉션에 대한

하나를 구현하는 3 개 속성을 당신의 콤보에서의 selectedItem에 대한 한을 (를 ObservableCollection에 확인) (당신은 결박 콤보 상자의 selectedItem합니다) 및 당신은 예를 들어) 데이터 그리드에

바인딩됩니다 다른 ObservableCollection에 당신은 XAML에 있습니다

<Grid> 
     <ComboBox ItemsSource="{Binding Products}" 
        SelectedItem="{Binding SelectedProduct}" 
        HorizontalAlignment="Left" 
        VerticalAlignment="Top" 
        Width="200" 
       Margin="20" 
       IsSynchronizedWithCurrentItem="True" /> 

    <DataGrid ItemsSource="{Binding SelectedOne}" 
       HorizontalAlignment="Right " 
       VerticalAlignment="Center" 
       Width="300" 
       IsSynchronizedWithCurrentItem="True"> 
    </DataGrid> 

그리고 ViewModel에서 이와 같은 것을 가질 수 있습니다.

 public ObservableCollection<Product> Products 
      { 
       get { return _products; } 
       set 
       { 
        if (value != _products) 
        { 
         _products = value; 
         OnPropertyChanged(); 
        } 
       } 
      } 

      private ObservableCollection<Product> _selectedOne; 
      public ObservableCollection<Product> SelectedOne 
      { 
       get { return _selectedOne; } 
       set { 
         _selectedOne = value; 
         OnPropertyChanged(); 
        } 
      } 

      public int SelectedProductId 
      { 
       get { return _selectedProductId; } 
       set 
       { 
        if (value != _selectedProductId) 
        { 
         _selectedProductId = value; 
         OnPropertyChanged(); 
        } 
       } 
      } 

      public Product SelectedProduct 
      { 
       get { return _selectedProduct; } 
       set 
       { 
        if (value ! = _selectedProduct) 

       { 
        _selectedProduct = value; 

        // clear your list of selected objects and then add just selected one 
        // or you dont clear it, and items will be added in DataGrid when selected in ComboBox 
        SelectedOne.Clear(); 
        SelectedOne.Add(_selectedProduct); 

        OnPropertyChanged(); 
       } 
      } 
     } 


     #region INotifyPropertyChanged Members 

     public event PropertyChangedEventHandler PropertyChanged = delegate { }; 

     protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "") 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 

     #endregion 

제품 채우기 코드 DataGrid는 ComboBox에서 항목을 선택하여 채워집니다.

u는 ViewModel 생성자에서 다음과 같이 만들 수 있습니다.

public MainWindowViewModel() 
     { 
      if (!DesignerProperties.GetIsInDesignMode(new DependencyObject())) 
      { 
       using (YourDbContext context = new YourDbContext()) 
       { 
        var productList = new ObservableCollection<Product>(context.Products); 
        productList.ToList() 
        Products = productsList; 
       } 
      } 
     } 
+0

DataGrid 또는 콤보 상자를 채우는 코드는 어디에 있습니까? –

+0

ViewModel에 목록을 채울 수있는 샘플을 추가했습니다. DataGrid는 ComboBox에서 Item을 선택하여 Populatet이 될 것입니다. 왜 SelectedOne 속성을 Collection으로 설정했는지, 그리고 DataGrid에 스택과 같은 항목을 더 추가하려면, 이전에 해당 컬렉션을 지우면 하나를 추가 할 수 있습니다. SelectedProduct 속성에서 만든 속성입니다. –