Нажатие кнопки WPF необходимо обновить привязку;Как мне это сделать? - PullRequest
0 голосов
/ 26 сентября 2018

У меня есть кнопка:

<Button Grid.Row="2" Grid.Column="0" Command="commands:Commands.BuyComponentCommand" CommandParameter="{Binding ElementName=inventory, Path=SelectedItem}" Click="btnBuy_Click">Buy</Button>

И поле со списком:

<ListBox Name="inventory" ItemsSource="{Binding Inventory}">
    ...
</ListBox>

И некоторые метки, которые я хочу обновить, чтобы увидеть, когда кнопка нажата;вот один из них:

<TextBlock Name="txtMineralsWarning" Foreground="Yellow" Text="You don't have enough minerals to buy this component." DataContext="{Binding ElementName=inventory, Path=SelectedItem}" Visibility="{Binding Converter={StaticResource NotEnoughMineralsToVisibilityConverter}}" TextWrapping="Wrap"/>

Теперь проблема в том, что ярлыки обновляют свою видимость, когда я выбираю другой элемент в ListBox;однако, когда я нажимаю кнопку, они не обновляют свою видимость, хотя нажатие на кнопку может повлиять на состояние, определяющее, должны ли метки быть видны в моем конвертере.

Вот метод преобразования моего конвертера, вна случай, если это поможет:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    var comp = (Component)value;
    if (comp == null)
        return Visibility.Hidden;
    if (comp.Cost > PlayerShip.Instance.Savings)
        return Visibility.Visible;
    return Visibility.Hidden;
}

Есть идеи, почему мои ярлыки не становятся видимыми, когда проверенное в преобразователе условие изменяется после нажатия кнопки?Я пробовал это безрезультатно:

private void btnBuy_Click(object sender, RoutedEventArgs e)
{
    txtMineralsWarning.GetBindingExpression(TextBlock.VisibilityProperty).UpdateTarget();
    txtCrewWarning.GetBindingExpression(TextBlock.VisibilityProperty).UpdateTarget();
}

1 Ответ

0 голосов
/ 26 сентября 2018

Вы должны сделать это с MVVM

Рабочий пример:

XAML:

<Window x:Class="WpfApp4.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:WpfApp4"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <StackPanel>
        <Button Command="{Binding ClickCommand}" Content="Click Me" />
        <TextBlock Text="Label" Visibility="{Binding LabelVisibility}" />
    </StackPanel>
</Window>

Код сзади:

public partial class MainWindow : Window {
    public MainWindow() {
        InitializeComponent();

        DataContext = new MainWindowViewModel();
    }
}

ViewModel:

public class MainWindowViewModel : INotifyPropertyChanged {
        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public ICommand ClickCommand => new RelayCommand(arg => DoExecuteClickCommand());

        private void DoExecuteClickCommand() {
            if (LabelVisibility == Visibility.Visible) {
                LabelVisibility = Visibility.Collapsed;
            } else {
                LabelVisibility = Visibility.Visible;
            }
            OnPropertyChanged(nameof(LabelVisibility));
        }

        public Visibility LabelVisibility { get; set; }
    }

    public class RelayCommand : ICommand {
        #region Fields

        readonly Action<object> _execute;
        readonly Predicate<object> _canExecute;

        #endregion // Fields

        #region Constructors

        /// <summary>
        /// Creates a new command that can always execute.
        /// </summary>
        /// <param name="execute">The execution logic.</param>
        public RelayCommand(Action<object> execute)
            : this(execute, null) {
        }

        /// <summary>
        /// Creates a new command.
        /// </summary>
        /// <param name="execute">The execution logic.</param>
        /// <param name="canExecute">The execution status logic.</param>
        public RelayCommand(Action<object> execute, Predicate<object> canExecute) {
            if (execute == null)
                throw new ArgumentNullException("execute"); //NOTTOTRANS

            _execute = execute;
            _canExecute = canExecute;
        }

        #endregion // Constructors

        #region ICommand Members

        [DebuggerStepThrough]
        public bool CanExecute(object parameter) {
            return _canExecute == null ? true : _canExecute(parameter);
        }

        public event EventHandler CanExecuteChanged {
            add => CommandManager.RequerySuggested += value;
            remove => CommandManager.RequerySuggested -= value;
        }

        public void Execute(object parameter) {
            _execute(parameter);
        }

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