WPF Переключение видимости элементов UIE в DataTemplate - PullRequest
3 голосов
/ 26 августа 2011

У меня есть DataTemplate, определяемый следующим образом

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

Я хочу иметь возможность переключать видимость TextBlock и TextBox каждый раз, когда пользователь нажимает на StackPanel.Я попытался установить обработчик событий 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 ]

1 голос
/ 18 октября 2011

Одним из решений является привязка видимости TextBox и TextBlock к свойствам класса, который используется как DataContext для StackPanel. Вот пример реализации:

Код Xaml:

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

И код C #:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        ObservableCollection<Some> items = new ObservableCollection<Some>();
        for (int i = 0; i < 10; i++)
        {
            items.Add(new Some(string.Format("passwordChar {0}", i + 1), string.Format("passwordText {0}", i + 1), Visibility.Visible, Visibility.Collapsed));
        }
        this.lbox.ItemsSource = items;
    }

    private void StackPanel_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        Some some = (sender as StackPanel).DataContext as Some;
        some.TextBlockVisibility = ToggleVisibility(some.TextBlockVisibility);
        some.TextBoxVisibility = ToggleVisibility(some.TextBoxVisibility);
    }
    private Visibility ToggleVisibility(Visibility visibility)
    {
        return visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
    }
}
public class Some:INotifyPropertyChanged
{
    private string _passwordChar;
    private string _passwordText;
    private Visibility _textBlockVisibility, _textBoxVisibility;

    public string PasswordChar { get { return this._passwordChar; } set { this._passwordChar = value; } }
    public string PasswordText { get { return this._passwordText; } set { this._passwordText = value; } }
    public Visibility TextBlockVisibility 
    { 
        get { return this._textBlockVisibility; } 
        set 
        { 
            this._textBlockVisibility = value;
            RaisePropertyChanged("TextBlockVisibility");
        }

    }
    public Visibility TextBoxVisibility 
    { 
        get { return this._textBoxVisibility; }
        set 
        { 
            this._textBoxVisibility = value;
            RaisePropertyChanged("TextBoxVisibility");
        }
    }

    public Some(string passwordChar, string passwordText, Visibility textBlockVisibility, Visibility textBoxVisibility)
    {
        this._passwordChar = passwordChar;
        this._passwordText = passwordText;
        this._textBlockVisibility = textBlockVisibility;
        this._textBoxVisibility = textBoxVisibility;
    }


    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
}
0 голосов
/ 26 августа 2011

Почему вы не связываете видимость элемента в вашей модели представления?

Пример.

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

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...