2012-02-04 68 views
5

在我的視圖模型和模型中,我有一個簽名爲bool IsPropertyReadOnly(string propertyName)的方法。此方法確定當前登錄的用戶是否可以編輯一個Propery值。一些用戶將能夠編輯屬性值,其他大多數用戶將擁有隻讀訪問權限。我如何將視圖模型方法的結果綁定到TextBox屬性?

我不想創建一個屬性來返回每個模型屬性的只讀狀態,我想將IsPropertyReadOny的結果綁定到TextBox.IsReadOnly屬性。

我這是怎麼設想的語法:

<TextBox Text="{Binding Address, Mode=TwoWay}" 
     IsReadOnly="{Binding MethodName=IsPropertyReadOnly MethodParameter=Address}" 
/> 

DataContext包含視圖模型,所以基本上我需要綁定IsReadOnly的號召((Class)this.DataContext).IsPropertyReadOnly("Address")

的結果有很多文檔中使用ObjectDataProvider,但對象數據提供程序創建一個新的對象實例,這不是我想要的。此外,要使用現有的實例,我必須在代碼隱藏中進行分配。再次,不是我想要做的。

從我的研究看來,從BindingMarkupExtension繼承的解決方案似乎更適合我的需要。

任何幫助將不勝感激。

+0

這裏可能是你的問題的答案(使用轉換器的最後一個答案):[?綁定到WPF的方法] (http://stackoverflow.com/questions/ 502250 /綁定到一個法功能於WPF) – 2012-02-04 21:25:18

回答

4

我建議使用轉換器。這裏是例子。假設你有一個簡單的ViewModel類:

class ViewModel 
{ 
    public string Read 
    { get; set; } 

    public string ReadWrite 
    { get; set; } 

    public bool IsPropertyReadOnly(string propertyName) 
    { 
     return propertyName != "ReadWrite"; 
    } 
} 

解決你的問題,你需要寫一個轉換器,如:

public class Converter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var vm = value as ViewModel; 
     var functionName = (string)parameter; 

     var result = vm.IsPropertyReadOnly(functionName); 
     return result; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotSupportedException("This method should never be called"); 
    } 
} 

而這一切;現在你可以在XAML中使用該轉換器,如:

<Window.Resources> 
    <temp:Converter x:Key="ReadOnlyMethodConverter"/> 
</Window.Resources> 
<StackPanel> 
    <TextBox Text="{Binding Read, Mode=TwoWay}" 
      IsReadOnly="{Binding Path=., 
     Converter={StaticResource ReadOnlyMethodConverter}, ConverterParameter=Read}" 
    /> 
    <TextBox Text="{Binding ReadWrite, Mode=TwoWay}" 
      IsReadOnly="{Binding Path=., 
     Converter={StaticResource ReadOnlyMethodConverter}, ConverterParameter=ReadWrite}" 
    /> 
</StackPanel> 

而在後臺代碼,我們只需要創建視圖模型,並設置爲的DataContext:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = new ViewModel(); 
    } 
} 
+0

即使我使用了H.B.的建議,在另一個答案中,我接受並對這個答案投了贊成票,因爲我認爲它完全回答了關於視圖模型上參數綁定方法的問題。 – AMissico 2012-02-08 07:20:44

+3

我認爲在以前的評論中有太多的答案。 :O) – AMissico 2012-02-08 07:22:59

0

您應該可以通過使用ObjectDataProvider來執行此方法,然後將附加屬性綁定到提供程序的返回值。

首先,您需要配置提供程序作爲一種資源:

<Window.Resources> 
    <ObjectDataProvider x:Key="readOnlyProvider" ...> 
    <ObjectDataProvider.MethodParameters> 
     ... 
    </ObjectDataProvider.MethodParameters> 
    </ObjectDataProvider> 
</Window.Resources> 

然後用提供商爲您的附加屬性的源綁定:

<TextBox Text="{Binding PoolNum, Mode=OneWay}" Windows:AttachedProperties.IsReadOnlyOn="{Binding Source={StaticResource readOnlyProvider}}" /> 

這個過程中最棘手的部分將「值」傳遞給ObjectDataProviders.MethodParameters。這可以在XAML中完成,並且有幾個資源可以告訴你它是如何完成的;這裏是一個開始:http://weblogs.asp.net/psheriff/archive/2010/02/23/bind-objectdataprovider-method-parameters-in-wpf.aspx

UPDATE

根據您的評論,這裏有兩種方式ObjectDataProvider可以執行方法上的視圖的DataContext,而無需創建一個新的對象。

首先,讓您的視圖模型方法靜態和使用ObjectType屬性:

<ObjectDataProvider x:Key="readOnlyProvider" 
    ObjectType="{x:local MyDataContext}" 
    MethodName="IsPropertyReadOnly"> 
    ... 
</ObjectDataProvider> 

或者,將供應商的ObjectInstance到視圖的DataContext當視圖加載:

public class MyWindow : Window 
{ 
    public MyWindow() 
    { 
    InitializeComponent(); 

    var readOnlyProvider = this.Resources["readOnlyProvider"] as ObjectDataProvider; 
    readOnlyProvider.ObjectInstance = this.DataContext; 
    } 
} 

有沒有辦法綁定到XAML中的方法以及我知道的使用ObjectDataProvider的唯一解決方法。

+0

不過,我不希望'ObjectDataProvider'創建一個新對象。如果我可以設置提供者的對象,這將是很好的。 – AMissico 2012-02-04 00:25:04

4

此外,使用現有的實例我必須在代碼隱藏中進行分配。再次,不是我想要做的。

這是不正確的,你的選擇,但將是有限的。


索引器怎麼樣?

private readonly Dictionary<string, bool> _PropertyReadOnlyDictionary = new Dictionary<string, bool>(); 
public Dictionary<string, bool> PropertyReadOnlyDictionary { get { return _PropertyReadOnlyDictionary; } } 
<TextBox Text="{Binding Address, Mode=TwoWay}" 
     IsReadOnly="{Binding PropertyReadOnlyDictionary[Address]}" /> 

你當然可以換你方法一個新的類,它允許通過一個索引訪問,以及如果你不想使用的字典。

private readonly PropertyIsReadOnlyResolver _PropertyIsReadOnlyResolver = new PropertyIsReadOnlyResolver(); 
public PropertyIsReadOnlyResolver PropertyIsReadOnlyResolver { get { return _PropertyIsReadOnlyResolver; } } 
public class PropertyIsReadOnlyResolver 
{ 
    public bool this[string propertyName] 
    { 
     get 
     { 
      return IsPropertyReadOnly(propertyName); 
     } 
    } 

    public bool IsPropertyReadOnly(string propertyName) 
    { 
     //... 
    } 
} 
<TextBox Text="{Binding Address, Mode=TwoWay}" 
     IsReadOnly="{Binding PropertyIsReadOnlyResolver[Address]}" /> 
+0

有趣的是,我們確實首先使用了一個索引器。我決定反對它,因爲我們需要使用'IDataErrorInfo'。我喜歡字典中的第一個索引器,因爲它更適合我們的實現。 – AMissico 2012-02-06 16:55:10

+0

我們使用了PropertyReadOnlyDictionary實現,它與我們的設計完美集成。非常感謝你。 – AMissico 2012-02-08 00:02:46

+0

@AMISSico:很高興聽到:) – 2012-02-08 07:07:58

相關問題