2013-08-01 53 views
0

我的目標是通過兩個不同的文本框更新單個Size屬性。特別是每個組件都連接到單個文本框(在下面的XAML中突出顯示)。具體這行:{綁定路徑= Dimensions.Width,...}將單個屬性的單個組件綁定到WPF中的兩個單獨控件

private Size _dimension; 
    public Size Dimensions 
    { 
     get { return _dimension; } 
     set 
     { 
      _dimension = value; 
      OnPropertyChanged("Dimensions"); 
     } 
    } 

我的XAML如下:

<StackPanel HorizontalAlignment="Left" Orientation="Horizontal"> 
    <Label Content="Width" /> 
    <TextBox Width="50" Text="{Binding Path=Dimensions.Width, 
      Converter={StaticResource myStringToDoubleConverter}, 
      UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/> 
    <Label Content="Height" /> 
    <TextBox Width="50" Text="{Binding Path=Dimensions.Height, 
      Converter={StaticResource myStringToDoubleConverter}, 
      UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/> 
</StackPanel> 

我的問題是所設定的功能不叫當我改變文本框中的文本時。我想是因爲我沒有提供一個Size對象,但最好是一個double對象,最壞的情況是一個字符串。我在那裏有一個轉換器來將字符串轉換爲double,但它似乎並不是個竅門。我的感覺是Multibinding產生我的解決方案,但是我看到的所有例子都是將兩個字符串合併到第三個控件中。我對使用附加值進行控制並不感興趣,而是更新我的「複雜」屬性的組件。

我明白我可以製作兩個「sub」屬性,Height和Width,然後一次更新一個Dimension的屬性,但似乎應該存在一個更優雅的解決方案。

爲什麼我的文本框不能正確綁定到Dimension屬性的單個組件並相應地更新維度?

構建一個實現INotifyPropertyChanged的包裝類似乎過分了。

public class MySizeClass : Size, INotifyPropertyChanged 
+0

我認爲你的答案是一個合理的解決方案。你原來的帖子中的代碼肯定有一些問題:1.你只能設置寬度,而不是高度。 2.您的轉換器如何將寬度轉換爲大小而不知道其高度?你如何堅持以前尺寸對象的高度? –

+0

@BillZhang轉換器實際上只是將字符串更改爲Double,而不是大小。要轉換爲尺寸,我需要以某種方式獲取高度參數。我不清楚,那實際上是可能的。除非我的轉換器做了一些特殊的地方,它只更新兩個組件之一。例如:return(new Size(input,this.Height)),但這並不是特別優雅,可能更糟糕...... 編輯:將OP中的代碼調整爲更統一。 – mwjohnson

+0

這將是顯而易見的。由於沒有隱式轉換器將Size轉換爲double,因此您的Size屬性絕對不會被調用。由於View Model是View的一個特殊模型,因此您應該考慮View如何方便地使用它的Model。 –

回答

3

如果您在此處使用的Size類型是由WPF提供的類型,即System.Windows.Size,那麼問題在於它不是類。這是一種價值類型(即struct)。儘管它確實爲WidthHeight提供了引導程序,但它可能不應該是因爲它們沒有達到你所期望的。

C#不會讓你修改Dimensions.Width要麼 - 如果你寫了以下內容:

src.Dimensions.Width = 123; 

其中src是包含在您的「組件綁定解決方案已經表明這些屬性定義的類型的實例」,你會得到這樣的錯誤:

Cannot modify the return value of 'WpfApplication1.Source.Dimensions' because it is not a variable

C#拒絕,因爲這種停止在WPF工作基本相同的問題在這裏:這是因爲Size是 值類型。任何檢索Dimensions屬性的嘗試都會返回值的全新副本。

當然,這C#代碼是有效簡稱:

Size dimensions = src.Dimensions; 
dimensions.Width = 123; 

C#實際上將讓你寫這篇文章,但如果你嘗試,你會發現它爲什麼攔你寫較短的版本:src.Dimensions.Width仍然會返回舊值。(這段代碼確實是需要的src.Dimensions副本,存儲在名爲dimensions一個局部變量拷貝,然後修改了局部變量,離開原來的不變。)

基本上,有沒有辦法去的一個參考Size您的Dimensions屬性返回的實例 - 您只能獲得該值的副本。而更新它的唯一方法是編寫一個完整的新代碼Size。這就是爲什麼你不能自己修改WidthHeight

試圖用轉換器解決這個問題是行不通的,因爲問題不是你試圖寫入目標的價值。問題是你想寫一個不可訪問的目標,即一個值類型的特定屬性。綁定只能寫入目標屬性,如果它是對象的屬性,而不是值。 (原則上,微軟可以讓WPF檢測到它,讓它讀取Dimensions屬性,修改它獲得的值的副本,然後將修改後的值寫回到Dimensions。儘管這在本文中會很方便從數據綁定通常處理更新屬性的方式來看,這也將是一個重大變化,我認爲它們可能會更好,因爲它可以很容易地掩蓋其他問題。)

在C#中,您可以當你有一個局部變量或包含Size值的字段時寫入單個屬性,因爲變量或字段表示該值的特定實例。字段,局部變量,refout參數和數組元素是特殊的,因爲實際上可以使用它們原位保存的值。但是在通過屬性時你無法做到這一點。如果你定義了一個List<Size>,你也不能寫myList[0].Width = 123;,即使這對於一個數組來說也不錯。

無論如何,可變值類型由於各種原因而存在問題,而不僅僅是這個。他們通常都會皺起眉頭,而且不幸的是WPF發佈了一些。

如果WPF能夠綁定到字段,你可以做你想做的。但事實並非如此,所以你不能。

+0

非常感謝,非常感謝。我常常被stackoverflow社區的專業知識和知識所吸引。你提到,「... System.Windows.Size,...不是一個類,它是一個值類型(即一個結構體)。」如果我要用兩個類型爲double的變量(Height和Width)創建一個新的Class MySize,然後使用該類型定義我的Dimensions屬性,此方法是否可行?即'公共MySize維度'因此使用類定義我的屬性,而不是內置的結構。 – mwjohnson

+1

是的,這應該工作。 –

1

這裏是組件綁定解決方案,它令人愉快地工作得很好。

private Double m_Width; 
    public Double Width 
    { 
     get { return (Dimensions.Width); } 
     set 
     { 
      m_Width = value; 
      Dimensions= new Size(m_Width, m_Height); 
     } 
    } 
    private Double m_Height; 
    public Double Height 
    { 
     get { return (Dimensions.Height); } 
     set 
     { 
      m_Height = value; 
      Dimensions= new Size(m_Width, m_Height); 
     } 
    } 
    private Size _dimension; 
    public Size Dimensions 
    { 
     get { return _dimension; } 
     set 
     { 
      _dimension = value; 
      OnPropertyChanged("Dimensions"); 
     } 
    } 

看來,直接綁定到Dimensions.Width是WPF所支持的東西。

相關問題