在WPF Samples中有一個關於資料繫結到方法的Demo,該Demo結構如下:
執行效果如下所示:
來看看是如何實現的。
先來看下MainWindow.xaml中的內容:
<Window.Resources>
<ObjectDataProvider ObjectType="{x:Type local:TemperatureScale}"
MethodName="ConvertTemp" x:Key="ConvertTemp">
<ObjectDataProvider.MethodParameters>
<system:Double>0</system:Double>
<local:TempType>Celsius</local:TempType>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<local:DoubleToString x:Key="DoubleToString" />
</Window.Resources>
在窗體資源中定義了一個ObjectDataProvider
物件與DoubleToString
物件。
ObjectDataProvider介紹
ObjectDataProvider
類用於包裝和建立可以用作繫結源的物件。
<ObjectDataProvider MethodName="ConvertTemp" >
ObjectDataProvider.MethodName
屬性獲取或設定要呼叫的方法的名稱。
<ObjectDataProvider.MethodParameters>
<system:Double>0</system:Double>
<local:TempType>Celsius</local:TempType>
</ObjectDataProvider.MethodParameters>
ObjectDataProvider.MethodParameters
屬性獲取要傳遞給方法的引數列表。
繫結到方法
<TextBox Grid.Row="1" Grid.Column="1" Name="tb">
<TextBox.Text>
<Binding Source="{StaticResource ConvertTemp}" Path="MethodParameters[0]"
BindsDirectlyToSource="true" UpdateSourceTrigger="PropertyChanged"
Converter="{StaticResource DoubleToString}">
<Binding.ValidationRules>
<local:InvalidCharacterRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
繫結路徑為方法的第一個引數。
使用的轉換器是在資源中定義的DoubleToString
。
BindsDirectlyToSource
屬性設定為true
,表示直接繫結到資料來源物件,而不是是繫結到資料來源物件的某個屬性。
<Binding.ValidationRules>
<local:InvalidCharacterRule/>
</Binding.ValidationRules>
Binding.ValidationRules
屬性用於定義資料繫結的驗證規則。這些規則用於在資料繫結過程中驗證輸入資料的有效性。如果資料不符合驗證規則,WPF 可以顯示錯誤資訊或採取其他措施來處理無效資料。
這裡使用的是InvalidCharacterRule
物件。
<ComboBox Grid.Row="1" Grid.Column="2"
SelectedValue="{Binding Source={StaticResource ConvertTemp},
Path=MethodParameters[1], BindsDirectlyToSource=true}">
<local:TempType>Celsius</local:TempType>
<local:TempType>Fahrenheit</local:TempType>
</ComboBox>
ComboBox
繫結到方法的第二個引數。
<Label Content="{Binding Source={StaticResource ConvertTemp}}"
Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2"/>
繫結到方法的返回值。
現在檢視這個方法:
public string ConvertTemp(double degree, TempType temptype)
{
Type = temptype;
switch (temptype)
{
case TempType.Celsius:
return (degree*9/5 + 32).ToString(CultureInfo.InvariantCulture) + " " + "Fahrenheit";
case TempType.Fahrenheit:
return ((degree - 32)/9*5).ToString(CultureInfo.InvariantCulture) + " " + "Celsius";
}
return "Unknown Type";
}
繫結過程梳理
該Demo啟動後的介面如下所示:
<ObjectDataProvider ObjectType="{x:Type local:TemperatureScale}"
MethodName="ConvertTemp" x:Key="ConvertTemp">
<ObjectDataProvider.MethodParameters>
<system:Double>0</system:Double>
<local:TempType>Celsius</local:TempType>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
在ObjectDataProvider.MethodParameters
中設定了方法的引數為0和Celsius。
而0是Double型別,TextBox需要string型別,因此設定了DoubleToString
轉換器。
該轉換器程式碼如下所示:
public class DoubleToString : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture) => value?.ToString();
public object ConvertBack(object value, Type targetType, object parameter,
CultureInfo culture)
{
var strValue = value as string;
if (strValue != null)
{
double result;
var converted = double.TryParse(strValue, out result);
if (converted)
{
return result;
}
}
return null;
}
}
<ComboBox Grid.Row="1" Grid.Column="2"
SelectedValue="{Binding Source={StaticResource ConvertTemp},
Path=MethodParameters[1], BindsDirectlyToSource=true}">
<local:TempType>Celsius</local:TempType>
<local:TempType>Fahrenheit</local:TempType>
</ComboBox>
ComboBox的SelectedValue
繫結到方法的第二個引數,剛開始也就是Celsius。
<Label Content="{Binding Source={StaticResource ConvertTemp}}"
Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2"/>
繫結到方法的返回值。
在TextBox中輸入了做了資料繫結的驗證規則。
InvalidCharacterRule
類程式碼如下所示:
internal class InvalidCharacterRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
var myvalue = 0.00;
try
{
if (((string) value).Length > 0)
myvalue = double.Parse((string) value);
}
catch (Exception e)
{
return new ValidationResult(false, "Illegal characters or " + e.Message);
}
return new ValidationResult(true, null);
}
}
當輸入不符合規則時,會有提示,如下圖所示:
程式碼來源
[WPF-Samples/Data Binding/BindingToMethod at main · microsoft/WPF-Samples (github.com)](https://github.com/microsoft/WPF-Samples/tree/main/Data Binding/BindingToMethod)