2016-10-05 5 views
2

저는 C#/WPF/Entity Framework DB에서 먼저 냉각수 선의 흐름 및 온도와 같은 값을 측정하는 독점 산업 하드웨어와 통신하는 응용 프로그램을 작성하고 있습니다. 이러한 값은 SQL Server 데이터베이스에서 백그라운드에서 실행되는 스레드로 자주 업데이트 된 다음 내 UI에 표시됩니다.데이터베이스 변경 사항으로 WPF UI를 업데이트하는 방법

내 관심사는 현재 이러한 변경 사항을 반영하기 위해 UI를 업데이트하는 방법입니다. 매 초마다 실행합니다

내 ViewModel에 내 데이터 컨텍스트를 설정하고, 스레드를 인스턴스화 : 여기가 데이터 그리드를 업데이트하는 방법의 예

_DataContext = new ViewModels.SummaryTable_ViewModel(); 
    this.DataContext = _DataContext; 
    UIUpdateThread = new Thread(UIUpdaterThread); 
    UIUpdateThread.IsBackground = true; 
    UIUpdateThread.Start();  

내 그리드의 기반이되는 모델은 IList의 <됩니다> 그것은 다음과 같습니다

private IList<channel> _channel; 
    public IList<channel> Channels 
    { 
     get 
     { 
      return _channel; 
     } 
     set 
     { 
      _channel = value; 
      //NotifyPropertyChanged(); 
      OnPropertyChanged("Channels"); 
     } 
    } 

그런 다음 매 초마다 내 UIUpdateThread은 다음과 같다() 메소드 내 FillChannels를 호출 한 후하여 PropertyChanged 알림을 기반으로 그리드 업데이트 :

using (var DTE = new myEntities()) 
      { 
       if (DTE.channels.Any()) 
       { 
        var q = (from a in DTE.channels 
          where a.setup.CurrentSetup == true 
          orderby a.ChannelNumber 
          select a).ToList(); 

        this.Channels = q; 
       } 
      } 

제 질문은 이것입니다. 더 좋은 방법이 있습니까? 이것은 더 나은 용어가 부족하여 "잘못"하다고 느낍니다. 그리고 스레드가 실행될 때마다 내 데이터 그릿에서 사용자 집합 정렬을 재설정하는 것과 같은 나쁜 부작용이 있습니다. 또한 MVVM 패턴이 깨지는 것은 확실하지만 확실하지 않습니다.

예를 들어 하드웨어에서 데이터를 찾기 위해 하드웨어를 폴링 할 때마다 내 하드웨어와 통신하는 스레드가 공유 채널 객체를 업데이트하고 UI 만 바인딩하면 어떻게 될지 생각하고 있습니다. 이 스레드 (또는 동일한 작업을 수행하는 다른 UI의 다른 스레드)를 실행하고 PropertyChanged 알림을 기반으로 업데이트하면됩니다. 아니면 내가 완전히 알지 못하는 다른 방법이 있습니까? 대답을 검색 할 때 내가 익숙하지 않은 작업 단위 패턴에 대한 언급이 여기에 관련 개념입니까?

여기서 알 수 있듯이, 나는 여기에서 어디로 가야할지 잘 모르겠다. 그리고 실제로 도움을받을 수있다. 텍스트의 벽에 죄송합니다. 가능한 한 철저히하고 싶었습니다. 어떤 도움이라도 대단히 감사하겠습니다. 감사.

+1

시작하려면 '채널'을 'ObservableCollection'으로 만듭니다. 항목이 추가되거나 제거되면 컬렉션을 다시 만드는 대신 항목을 추가/제거합니다. 일반적으로 두 번째 단락부터 마지막 ​​단락까지는 돈이됩니다 : 적절한 변경 통보를하는 기존의 변경. 전체적으로 새로운 현재 상태에서 단순히 뛰어 드는 것과 관련하여 다소 엉키지 만, 그렇게해야 할 경우, 그렇게해야합니다. P.S .: rory.ap이 말한 것. –

+0

도움 주셔서 감사합니다. @EdPlunkett – user3900520

답변

4

여러분의 모델은 새로운 데이터가있을 때 뷰 모델을 알려주는 모델이어야한다고 생각합니다. 이 작업을 수행하는 모든 메커니즘 (예 : 사용중인 것으로 가정하는 타이머)을 모델에 넣어야합니다.

기본적으로 모델은 뷰 모델에 알리고 뷰 모델은 데이터 변경이 있음을 뷰에 알립니다. 보기를 올바르게 설정하고 코드 숨김 대신 XAML을 사용하면보기와보기 모델 간의 데이터 바인딩을 통해 자동으로 함께 제공됩니다.

정렬 관련 :보기 그리드의 정렬 속성에 바인딩 된보기 모델의 별도 속성이어야합니다. 모델이 사용자 설정 정렬을 유지해야하며 데이터가 변경 될 때 뷰 모델에 알리기 전에 업데이트 된 데이터에 적절하게 적용해야합니다.

관련된 작업 행을 여러 테이블에 보존하고 하나의 트랜잭션으로 수행하는 것에 대해 이야기하고 있지 않기 때문에 작업 단위를 적용 할 수 있는지 확실하지 않습니다. 데이터를 읽는 것뿐입니다. 나는 일의 단위를 그다지 공부하지 않았기 때문에 잘못 될 수있다.


는 의견에 질문을 해결하기 위해 :

이의 다시 단계를 보자. 귀하의 뷰 모델은 에만 해당 뷰의 표시와 관련된 논리가 있어야합니다. 비즈니스 로직 또는 도메인 관련 태스크를 수행하는 데이터 액세스 코드 나 코드가 없어야합니다. 그 코드는 집합 적으로 "모델"이라고 불리는 것에 들어갑니다. (이미이 코드가 있으면 저를 용서해주십시오. 그러나 질문에 제공 한 코드가 어디에 있는지 정확하게 말하기는 어렵습니다.)

모델은 다양한 비즈니스 로직 작업을 수행하거나 (엔터티 프레임 워크 생성 클래스와 같이) 도메인/엔터티 POCO를 나타내는 많은 클래스로 구성 될 수 있습니다.

Channel 개체가 무엇이고 개체 클래스/POCO, 즉 EF 생성 모델과 어떻게 다른지 약간 확실하지 않습니다. 그러나 EF와의 상호 작용 및 엔티티와 관련된 유지 관리 및 논리가 모델에서 발생해야합니다.

그렇습니다. 원하는 메커니즘을 사용하여 모델에서 데이터 변경 사항을 찾는 것이 좋습니다. 타이머 (btw에는 동기식으로 실행되는 타이머가 있으므로 "타이머"라는 개념을 "스레드"와 함게 사용하지 마십시오) 또는 엔티티 모음의 "콜렉션 변경"이벤트에 직접 바인딩하십시오. 변경 사항이 감지되면 모델에서 해당 변경에 필요한 비즈니스 로직 (변환, 정렬, 로깅 등 적용)을 수행 한 다음 변경이 발생했다는 사실을 뷰 모델에 알리기 만하면됩니다.

+0

좋습니다. 우선, 도움에 감사드립니다. 이 인스턴스에서 내 모델이 무엇인지 제대로 이해했는지 확인하려면? Entity Framework에서 자동으로 생성 된 모델입니까? 그렇다면 CodeFirst로 변환해야만 해당 코드를 변경할 수 있습니다. 아니면 내 viewmodel에있는 Channel 객체입니까? 내가 지금하는 것처럼 데이터베이스를 자주 쿼리하는 모델에 스레드를 넣고 바로 바인딩하는 아이디어입니까? CollectionChanged 이벤트가 발생하여 내 UI가 업데이트됩니까? (내 컬렉션이 편집 된 것 이상으로/removedfrom을 추가했기 때문에 필요한 것임을 가정합니다. – user3900520

+0

@ rory.ap의 버그를 혐오합니다. 위의 설명에서 내 질문을 편집했습니다. 약간의 설명 만 사용했을 수 있습니다. 내 모델/모델이 의미하는 바를 어디에서 업데이트 할 필요가 있는지에 대해 알고 있습니다.이 점을 이해하는 데 매우 가깝습니다. 그 답이 유일한 답 이었기 때문에 답을 받아 들였습니다. 나는 경험이 부족하기 때문에 조금 혼란스러워. 어느 쪽이든, 다시 한번 감사드립니다. – user3900520

+1

@ user3900520 - 문제 없습니다. 내 업데이트를 참조하십시오. –

관련 문제