将 URI 绑定到文本框

Binding a URI to a textbox

我有一个 属性 类型的 System.URI,我将它绑定到一个文本框。这似乎工作得很好,除非我输入类似 https://stackexchange.com/ 的东西,它不会让我输入 / 因为我得到:

System.Windows.Data Error: 7 : ConvertBack cannot convert value 'http://' (type 'String'). BindingExpression:Path=webURL; DataItem='ItemViewModel' (HashCode=66245186); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String') UriFormatException:'System.UriFormatException: Invalid URI: The hostname could not be parsed.
   at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
   at System.Uri..ctor(String uriString, UriKind uriKind)
   at System.UriTypeConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   at MS.Internal.Data.DefaultValueConverter.ConvertHelper(Object o, Type destinationType, DependencyObject targetElement, CultureInfo culture, Boolean isForward)
   at MS.Internal.Data.SourceDefaultValueConverter.ConvertBack(Object o, Type type, Object parameter, CultureInfo culture)
   at System.Windows.Data.BindingExpression.ConvertBackHelper(IValueConverter converter, Object value, Type sourceType, Object parameter, CultureInfo culture)'

然后我尝试了一个转换器将 URI 转换为一个字符串,认为这是问题所在:

public override object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    Uri input = value as Uri;
    if (input == null) return String.Empty;
    else return input.ToString();
}

public override object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    string input = value as string;
    if (String.IsNullOrEmpty(input)) return null;
    else return new Uri(input, UriKind.RelativeOrAbsolute);
}

这更糟,因为如果 URI 无效,这实际上会爆炸。

有没有办法将 URI 直接绑定到文本框?或者我只需要在我的视图模型中使用“代理”属性 来保存字符串值。我想直接绑定到 URI 的原因是我有 IDataError 验证,即检查 URI 的有效性,效果很好。

我实现了你的转换器并且它工作了,虽然我不必使用 override 关键字。

我的 XAML 是:

<Window.Resources>
    <Converter:UriToStringConverter x:Key="UriStringToConverter"/>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <TextBox Grid.Row="0"
             Margin="5"
             Text="{Binding Url, Converter={StaticResource UriStringToConverter}}" />
    <TextBlock Grid.Row="1"
               Margin="5"
               Text="{Binding Url, Converter={StaticResource UriStringToConverter}}"/>
</Grid>

Url 属性 被定义为:

    private Uri url = new Uri("http://example.com");
    public Uri Url
    {
        get { return url; }
        set
        {
            url = value;
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Url"));
        }
    }

其中 class 实现了 INofifyPropertyChanged 接口。

请注意,我必须使用有效 url 初始化 Uri,否则会引发异常。即使我输入(例如)"test",它也会成功地将其转换回 Uri(尽管无效)。