WPF Как из одного UserControl перейти в другой UserControl по нажатию на кнопку на первом
Как в главной форме по нажатию кнопки в первом UserControl отрылся 2 UserControl, а первый закрылся. Пытаюсь решить эту простую задачу уже 2 день. Можно показать пример, как реализовать эту задачу.
Ответы (1 шт):
UserControl в плане Visibility ничем не отличается от любого другого контрола, так как у них общий родитель UIElement.
Следовательно можно вопрос поставить так: При нажатии кнопки один TextBox должен прятаться, а второй появляться на его месте.
Создаем класс, реализующий интерфейс INotifyPropertyChanged, далее от него можно наследовать любой другой класс для работы с свойствами, умеющими обновлять интерфейс.
public class NotifyPropertyChanged : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
Далее, можно создать отдельный класс, хранящий свойства, предназначенные для главного окна. В шаблоне программирования MVVM его обычно называют MainViewModel, так его и назову.
public class MainViewModel : NotifyPropertyChanged
{
private bool _visibleState;
public bool VisibleState
{
get => _visibleState;
set
{
_visibleState = value;
OnPropertyChanged(); // сообщает привязанным сюда биндингам, что свойство поменялось.
}
}
}
VisibleState как раз и будет отвечать за то, какой из текстбоксов будет показан.
Далее, чтобы кнопка могла вызывать какой-то код (я знаю про событие Click), нужна команда. Чтобы удобно использовать команды, есть такой шаблонный класс-помощник, реализующий интерфейс ICommand.
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Func<object, bool> _canExecute;
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute == null || _canExecute(parameter);
public void Execute(object parameter) => _execute(parameter);
}
И доработаю MainViewModel, создам команду, которая будет менять VisibleState.
public class MainViewModel : NotifyPropertyChanged
{
private bool _visibleState;
private ICommand _changeVisibleStateCommand;
public bool VisibleState
{
get => _visibleState;
set
{
_visibleState = value;
OnPropertyChanged();
}
}
public ICommand ChangeVisibleStateCommand =>
_changeVisibleStateCommand ?? (_changeVisibleStateCommand = new RelayCommand(parameter =>
{
VisibleState = !VisibleState;
}));
}
Все готово, теперь собрать это воедино. Чтобы MainViewModel заработала, ее надо создать и присвоить свойству DataContext главного окна. Самый простой способ для новичков - сделать это в конструкторе окна.
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
Отлично, теперь можно использовать привязки Binding.
Вот полная разметка.
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<StackPanel Orientation="Vertical">
<Button Margin="5" Content="Click me!" HorizontalAlignment="Left" Command="{Binding CangeVisibleStateCommand}"/>
<TextBox Margin="5" Text="1st TextBox">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding VisibleState}" Value="True">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<TextBox Margin="5" Text="2nd TextBox">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding VisibleState}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</StackPanel>
</Grid>
</Window>
Вот и все, пример готов. При нажатии на кнопку, один TextBox скрывается, второй появляется на его месте, при повторном нажатии наоборот.
С UserControl все в точности то же самое, как и с любым другим контролом.