将文本框的Text属性绑定到Watermark附加属性以进行本地化

3

我需要为我的WPF应用程序添加水印,我正在使用此水印服务来实现它。

它的工作效果与预期一致,但我需要将水印显示的文本本地化,但我找不到实现它的方法。

我的xaml声明如下:

<TextBox
    Text="{Binding Name, Mode=TwoWay}">
    <Watermark:WatermarkService.Watermark>
        <TextBlock
            Text="{Binding <What-goes-here?>}"
        />
    </Watermark:WatermarkService.Watermark>
</TextBox>

我的视图模型:
public class PersonViewModel
{
    public string Name {get;set;}

    public string NameWatermark {get;set;}
}

以下代码行不起作用:
Text="{Binding NameWatermark}"

<Window x:Name="ThisWindow"
...
Text="{Binding Path=NameWatermark,
               ElementName=ThisWindow}"

有没有办法实现它?
非常感谢您提供的任何帮助。
2个回答

3

我知道这个问题很古老,但对于谷歌时间旅行者来说,我遇到了完全相同的问题,并通过使用MultiDataTrigger来隐藏/显示水印元素来解决了它。 它之所以有效,是因为它没有像原始的Watermark:WatermarkService.Watermark那样将元素嵌入到adorner中。

<Grid>
    <TextBox x:Name="messageBox" Text="{Binding Message, UpdateSourceTrigger=PropertyChanged}" Padding="5">
        <TextBox.InputBindings>
            <KeyBinding Key="Enter" Command="{Binding SendMessageCommand}"/>
        </TextBox.InputBindings>
    </TextBox>
    <TextBlock Text="{text:Translate Key=WriteMessageWatermark}" IsHitTestVisible="False" Foreground="LightGray" Margin="7,6,0,0">
        <TextBlock.Style>
            <Style TargetType="TextBlock">
                <Setter Property="Visibility" Value="Collapsed" />
                <Style.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding ElementName=messageBox, Path=Text.IsEmpty}" Value="True" />
                            <Condition Binding="{Binding ElementName=messageBox, Path=IsFocused}" Value="False" />
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Visibility" Value="Visible" />
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>
</Grid>

0

我认为问题在于WatermarkService只是一个静态类,没有依赖对象,因此无法正确继承其内容的DataContext。

首先:您真的需要绑定到ViewModel吗?我假设您想本地化UI的更多部分,因此将此内容移动到专用服务可能是一种选择。

像这样:

<Watermark:WatermarkService.Watermark>
  <TextBlock Text="{Binding Source={x:Static Watermark:LocalizationService.Instance}, Path=[123],FallbackValue='No LocalizationService found'}"/>
</Watermark:WatermarkService.Watermark>

本地化的单例类:

    private static volatile LocalizationService _instance;
    private static object syncRoot = new Object();

    public static LocalizationService Instance
    {
      get
      {
        if (_instance == null)
        {
          lock (syncRoot)
          {
            if (_instance == null)
              _instance = new LocalizationService();
          }
        }

        return _instance;
      }
    }

    public string this[int id]
    {
      get
      {
        // do localization stuff here ... 
        return "Localized Value " + id;
      }
    }
  }

如果您真的想要绑定到窗口的DataContext,您可以使用以下解决方法,通过将ViewModel分配给ObjectDataprovider并在绑定中访问它:
  <Grid Loaded="Grid_Loaded">
    <Grid.Resources>
      <ObjectDataProvider x:Key="PersonViewModelProvider" ObjectInstance="{x:Null}" IsAsynchronous="True"/>
    </Grid.Resources>
    <TextBox Text="{Binding Name, Mode=TwoWay}">
      <Watermark:WatermarkService.Watermark>
        <TextBlock Text="{Binding Source={StaticResource PersonViewModelProvider}, Path=NameWatermark}"/>
      </Watermark:WatermarkService.Watermark>
    </TextBox>
  </Grid>

代码后台:

private void Grid_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
  var panel = sender as Panel;
  if (panel != null)
  {
    var objDataProvider = panel.Resources["PersonViewModelProvider"] as ObjectDataProvider;
    objDataProvider.ObjectInstance = panel.DataContext;
  }
}

谢谢您的回复。我目前正在使用这个库来本地化WPF:http://www.codeproject.com/Articles/249369/Advanced-WPF-Localization,但我找不到使用它进行本地化的方法。这就是我将其绑定到ViewModel(从Resources.resx文件获取Watermkar值)的原因。也许我可以改编LocExtension类来应用您的第一种选项。 - JoanComasFdz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接