在Watermark附加属性中绑定TextBox.Text以对其进行本地化

时间:2012-03-14 10:57:33

标签: wpf binding localization watermark attached-properties

我需要在我的WPF应用程序中添加水印,并使用this watermark service来实现它。

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

我的xaml声明:

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

我的ViewModel:

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 个答案:

答案 0 :(得分:2)

我意识到这个问题很古老,但对于谷歌时间旅行者来说,我遇到了完全相同的问题并通过使用MultiDataTrigger来隐藏/显示水印元素来解决它。它的工作原理是因为它没有将元素嵌入到原始Watermark:WatermarkService.Watermark之类的装饰器中。

<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>

答案 1 :(得分: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;
  }
}