WPF切换DataTemplate中UIElements的可见性

时间:2011-08-26 03:27:42

标签: c# wpf xaml datatemplate uielement

我的DataTemplate定义如下

<DataTemplate x:Key="PasswordViewerTemplate">
  <StackPanel>
    <TextBlock Text="{Binding PasswordChar, ElementName=this}"
               Visibility="Visible" />
    <TextBox Text="{Binding PasswordText}"
             Visibility="Collapsed" />
  </StackPanel>
</DataTemplate>

每次用户点击TextBlock时,我希望能够切换TextBoxStackPanel的可见性。我尝试在MouseLeftButtonUp上设置StackPanel事件处理程序,但这会引发异常

  

Object reference not set to an instance of an object

还有另一种方法可以达到这个目的吗?也许在XAML本身使用触发器?

此外,这可能是相关的。上述模板是模板选择器应用于ListBox的两个模板之一。 ListBox本身位于Grid范围内,两个模板都在Grid.Resources部分内定义。

编辑1
我尝试将事件设置如下

<StackPanel MouseLeftButtonUp="OnPasswordViewerMouseLeftButtonUp">
...
</StackPanel>
private void OnPasswordViewerMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
  var sp = sender as StackPanel;
  if( ( sp == null ) || ( sp.Children.Count != 2 ) ) {
    return;
  }

  var passwordText = sp.Children[0] as TextBlock;
  var plainText = sp.Children[1] as TextBox;
  if( ( passwordText == null ) || ( plainText == null ) ) {
    return;
  }

  passwordText.Visibility = ( passwordText.Visibility == Visibility.Visible ) ? 
    Visibility.Collapsed : Visibility.Visible;
  plainText.Visibility = ( plainText.Visibility == Visibility.Visible ) ?
    Visibility.Collapsed : Visibility.Visible;
}

2 个答案:

答案 0 :(得分:1)

其中一个解决方案是将TextBoxTextBlock的可见性绑定到类的属性,该属性用作DataContext的{​​{1}}。以下是一个示例实现:

Xaml代码:

StackPanel

和C#代码:

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="PasswordViewerTemplate">
            <StackPanel PreviewMouseUp="StackPanel_PreviewMouseUp">
                <TextBlock Text="{Binding Path=PasswordChar}"
           Visibility="{Binding Path=TextBlockVisibility}" />
                <TextBox Text="{Binding Path=PasswordText}"
         Visibility="{Binding Path=TextBoxVisibility}" />
            </StackPanel>
        </DataTemplate>
    </Grid.Resources>
    <ListBox x:Name="lbox" ItemTemplate="{StaticResource ResourceKey=PasswordViewerTemplate}" ItemsSource="{Binding}"/>
</Grid>

答案 1 :(得分:0)

为什么不在视图模型中绑定项目的可见性?

一个例子。

<Textblock Test="{Binding passwordText,ElementName=This}" Visibility="{Binding passwordTextVisibility}"/>
你的ViewModel中的

public Visibility passwordTextVisibility
{
 getters and setters here
}

并且在您的鼠标事件中,您需要在堆栈面板内部进行某种路由事件。一个例子:

在堆栈面板中你需要鼠标。无论你需要什么。阅读一些关于路由事件的信息

实施例。如果PreviewMouseLeftButtonUp不起作用。

<StackPanel Mouse.MouseUp="MouseButtonUpEventHandler"/>

在视图模型中

public void MouseButtonUpEventHandler (RoutedEvent e)
{
//logic here to check if it's left mouse if it is then set visibility
}

}