2010-05-04 4 views
0

다음 클래스를 사용합니다 (단순화하기 위해). 다중 스레드 방식의 앱이므로 Set 및 Get은 좀 더 복잡하지만 괜찮습니다.WFP : 종속성 속성을 GUI에 올바르게 바인딩하는 방법

<Window x:Class="News.Main" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:converter="clr-namespace:News.Converters" 
    xmlns:local="clr-namespace:News.Lookup" 
    xmlns:rss="clr-namespace:News.RSS" 
    Title="News" Height="521" Width="927" Initialized="Window_Initialized" Closing="Window_Closing" > 
    <Window.Resources> 
     <ResourceDictionary> 
     <converter:BooleanConverter x:Key="boolConverter" /> 
     <converter:ArithmeticConverter x:Key="arithConverter" /> 
      ... 
     </ResourceDictionary> 
    </Window.Resources> 
    <DockPanel Name="dockPanel1" SnapsToDevicePixels="False" > 
     <ToolBarPanel Height="37" Name="toolBarPanel" Orientation="Horizontal" DockPanel.Dock="Top" > 
      <ToolBarPanel.Children> 
        <Button DataContext="{DynamicResource FeedEngine}" HorizontalAlignment="Right" Name="btnSearch" ToolTip="Search" Click="btnSearch_Click" IsEnabled="{Binding Path=Processing, Converter={StaticResource boolConverter}}"> 
        <Image Width="32" Height="32" Name="imgSearch" Source="{Resx ResxName=News.Properties.Resources, Key=Search}" /> 
       </Button> 
       ... 
    </DockPanel> 
</Window> 

당신은 내가 FeedEngine에 DataContext를 설정보고 및 처리에 바인딩의 IsEnabled 수 있듯이 :

namespace News.RSS 
{ 
    public class FeedEngine : DependencyObject 
    { 

     public static readonly DependencyProperty _processing = DependencyProperty.Register("Processing", typeof(bool), typeof(FeedEngine), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender)); 
     public bool Processing 
     { 
      get 
      { 
       return (bool)this.Dispatcher.Invoke(
        DispatcherPriority.Normal, (DispatcherOperationCallback)delegate { return GetValue(_processing); }, Processing); 
      } 
      set 
      { 
       this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, 
        (SendOrPostCallback)delegate { SetValue(_processing, value); }, 
        value); 
      } 

    } 

    public void Poll() 
    { 
     while (Running) 
     { 
      Processing = true; 
      //Do my work to read the data feed from remote source 
      Processing = false; 
      Thread.Sleep(PollRate); 
     } 
     // 
    } 
} 

}

다음으로 나는 다음과 같은 내 주요 형태가있다. 나는 또한 boolConverter를 개별적으로 테스트했고 기능을 수행했다. (그냥 bool에! (Not)를 적용한다.)

다음은 내 메인 윈도우 코드입니다. 디버깅에 도움이됩니다.

namespace News 
{ 
    /// <summary> 
    /// Interaction logic for Main.xaml 
    /// </summary> 
    public partial class Main : Window 
    { 
     public FeedEngine _engine; 
     List<NewsItemControl> _newsItems = new List<NewsItemControl>(); 
     Thread _pollingThread; 

     public Main() 
     { 
      InitializeComponent(); 
      this.Show(); 
     } 


     private void Window_Initialized(object sender, EventArgs e) 
     { 
      // Load current Feed data. 
      _engine = new FeedEngine(); 
      ThreadStart start = new ThreadStart(_engine.Poll); 
      _pollingThread = new Thread(start); 
      _pollingThread.Start(); 
     } 

    } 
} 

누군가가 내가 단계를 놓친 곳을 볼 수 있기를 바랍니다.

감사합니다.

+0

어디에서 FeedEngine DynamicResource를 정의합니까? 일반적으로 디버그 빌드에서 실행되는 동안 출력 창을 체크 아웃해야합니다. 진단에 도움이되는 바인딩 오류가 있음을 알 수 있습니다. –

답변

1

가장 명백한 문제는 DependencyProperty를 올바르게 사용하지 않는다는 것입니다. 모든 DependencyProperty에 대해 래퍼 속성은 GetValue 및 SetValue에 대한 상용구 호출을 유지해야하며 다른 코드를 포함하지 않아야합니다. 이것의 주된 이유는 일부 사용 시나리오 (XAML 포함)는 래퍼 속성을 속성에 액세스 (제거하려고 함)하고 Get/SetValue에 대한 직접 호출을 대신하는 실제 Get/Set를 나타내는 표시기로만 사용한다는 것입니다. setter에서 일반적으로 수행되는 추가 작업은 Register 호출의 추가 매개 변수로 연결된 PropertyChanged 핸들러에 넣어야합니다.

배경 스레드에서 처리를 설정하고 UI의 바인딩에서 그것을 읽는 것이 좋습니다. DependencyProperty는 생성 스레드 (이 경우와 대부분 UI 스레드)에서 소유하므로, 값을 설정할 때 Dispatcher.BeginInvoke 코드가 필요하지만 Poll()과 같이 다른 곳으로 이동해야합니다. DependencyObject 대신 INotifyPropertyChanged를 사용하는 경우에도 마찬가지입니다. 여기에서 코드를 기반으로 할 수 있습니다.

+0

변화가 있었지만 여전히 차이가 없었습니다. 단추의 속성은 변경되지 않습니다. }) 여기서 폴 공개 무효 폴() { 동안 (실행) { this.Dispatcher.Invoke (DispatcherPriority.Normal 새로운 액션 (대리인() {가공 = TRUE의 변화의 예는); 물론 get 및 set 자체에서 Dispatcher.Invoke 호출을 제거했습니다. –

관련 문제