如果方法抛出异常,则更改textblock的前景

时间:2018-12-01 15:06:33

标签: c# wpf mvvm

我有一堂课(可以从互联网获取公共IP)

public class GetPublicIP
{
    public string GetIPAddress()
    {
        string address = "";
        try
        {
            WebRequest request = WebRequest.Create("http://checkip.dyndns.org/");
            using (WebResponse response = request.GetResponse())
            using (StreamReader stream = new StreamReader(response.GetResponseStream()))
            {
                address = stream.ReadToEnd();
            }

            int first = address.IndexOf("Address: ") + 9;
            int last = address.LastIndexOf("</body>");
            address = address.Substring(first, last - first);
        }
        catch (Exception)
        {
            address = "Click To Check On Browser";
            //PublicIPTextBox.Foreground = new SolidColorBrush(Colors.IndianRed);
            //PublicIPTextBox.FontWeight = FontWeights.SemiBold;
        }
        return address;
    }

    //Currently using this  if its value is true i am changing foreground and fontweight in code behind
    public bool ExceptionOccurs()
    {
        bool returning = false;
        if (GetIPAddress() == "Click To Check On Browser")
            returning =  true;
        return returning;
    }
}

但是问题是,每当它捕获异常时,我都需要更改Xaml页面/视图中存在的textblock前景和字体粗细,如果直接将其放在代码后面,则没有问题,我可以直接更改前景和字体粗细,但是如果它是一个单独的类,则该方法。我想在mvvm模式中得到一个答案,我现在在同一个类中得到布尔结果

1 个答案:

答案 0 :(得分:1)

好的,这是一些代码:

XAML:

    <Window x:Class="WpfApp5.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:WpfApp5"
            mc:Ignorable="d"
            WindowStartupLocation="CenterScreen"
            SizeToContent="WidthAndHeight"
            Title="MainWindow" Height="450" Width="800" d:DataContext="{d:DesignInstance local:MainWindowViewModel}">
        <Grid Margin="10">
            <StackPanel>
                <Button Content="GetIP" Command="{Binding GetIpCommand}" Margin="5" Padding="5" />
                <TextBox Text="{Binding IpAddress, Mode=OneWay}" Foreground="{Binding IpForeground}" Width="200" Margin="5"/>
            </StackPanel>
        </Grid>
    </Window>

和代码:

    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
            DataContext = new MainWindowViewModel();
        }
    }

    public class MainWindowViewModel : INotifyPropertyChanged {
        private string _ipAdrress;
        private bool _errorOccured;
        public event PropertyChangedEventHandler PropertyChanged;

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

        public string IpAddress => _ipAdrress;
        public Brush IpForeground => _errorOccured ? new SolidColorBrush(Colors.Red) : new SolidColorBrush(Colors.Black);

        public ICommand GetIpCommand {
            get { return new RelayCommand(param => DoExecuteGetIpCommand()); }
        }

        private async void DoExecuteGetIpCommand() {
            try {
                _errorOccured = false;
                _ipAdrress = await MyService.GetIpAddress();
            } catch (Exception ex) {
                _errorOccured = true;
                _ipAdrress = ex.Message;
            }
            OnPropertyChanged(nameof(IpAddress));
            OnPropertyChanged(nameof(IpForeground));
        }
    }

    internal class MyService {
        private static bool _dummySucces = false;
        public async static Task<string> GetIpAddress() {
            //TODO Code to get IP in async manner...
            _dummySucces = !_dummySucces;

            if (!_dummySucces) {
                throw new Exception("Error occured...");
            }
            return "1.1.1.1";
        }
    }
    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
    }

要查看结果,请在按钮上单击多次...

要连接View和ViewModel,您应该在实际项目中使用依赖注入或类似的方法...