2010-05-04 55 views
0

我有以下類(爲了簡化起見,簡化了)。該應用程序多線程,所以設置和獲取有點複雜,但應該沒問題。WFP:您如何正確地將DependencyProperty綁定到GUI

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); 
     } 
     // 
    } 
} 

}

接下來我有我的主要形式如下:

<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> 

正如你可以看到我設置的DataContext到FeedEngine和綁定的IsEnabled來處理。我也測試了boolConverter分開和它的功能(只適用!(不))到布爾)。

這是我的主窗口代碼,以防萬一它有助於調試。

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?一般來說,一定要在Debug Build中運行時檢出Output窗口。你可以在那裏看到任何綁定失敗以幫助診斷。 – 2010-05-04 02:39:58

回答

1

最明顯的問題是您沒有正確使用DependencyProperty。對於任何DependencyProperty,包裝屬性應該堅持對GetValue和SetValue的樣板調用,並且不包含其他代碼。主要原因是某些使用場景(包括XAML)僅使用包裝屬性作爲可以訪問該屬性的指示器(嘗試刪除它),而實際的get/set則直接調用GetValue/SetValue。通常在setter中執行的任何其他操作都應該放入一個PropertyChanged處理程序中,該處理程序作爲Register調用中的附加參數附加。

它看起來像你想要從你的後臺線程設置Processing並從UI中的綁定中讀取它。由於DependencyProperty屬於它的創建線程(在這個和大多數情況下是UI線程),所以在設置值時需要使用Dispatcher.BeginInvoke代碼,但它應該移到其他地方 - 比如到Poll()中。如果您使用的是INotifyPropertyChanged而不是DependencyObject,則可以這樣做,您可以根據此處的代碼進行操作。

+0

進行了更改,仍然沒有區別。按鈕上的屬性不會改變。以下是在輪詢 公共無效輪詢() { 而(運行) { this.Dispatcher.Invoke(DispatcherPriority.Normal,新行動(委託(){處理=真所變化的一個例子;}) ); 當然,我從屬性獲取並設置它自己刪除Dispatcher.Invoke調用。 – 2010-05-04 23:40:35