Наследование: INotifyPropertyChanged
        public Settings()
        {
            InitializeComponent();

            _mvm = Application.Current.MainWindow.DataContext as MainViewModel;
            apiKeyTextBox.Text = _mvm.ApiKey;
            subdomainTextBox.Text = _mvm.Subdomain;
            overlayPath.Text = Properties.Settings.Default.overlayPath;
            saveChallonge.IsChecked = Properties.Settings.Default.challonge_save;
            enableScoreboard.IsChecked = Properties.Settings.Default.enableScoreboard;
            showInstructions.IsChecked = Properties.Settings.Default.showInstructions;
            roundDisplay.SelectedIndex = Properties.Settings.Default.roundDisplayType;

            Update_Challonge_Checkbox();
            Update_Scoreboard_Checkbox();
        }
        public OrganizerViewModel(MainViewModel mvm, System.Threading.SynchronizationContext dispatcher)
        {
            Mvm = mvm;

            OpenMatches = new ObservableCollection<DisplayMatch>();
            OpenStations = new ObservableCollection<Station>();

            var mvmPropertyChanged = Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(h => mvm.PropertyChanged += h, h => mvm.PropertyChanged -= h);

            //Monitor if matches change (for example on a bracket reset)
            matchesMonitoring = mvmPropertyChanged.Where(ep => ep.EventArgs.PropertyName == "DisplayMatches")
                .Select(_ => System.Reactive.Unit.Default).StartWith(System.Reactive.Unit.Default).Where(_ => mvm.DisplayMatches != null)
                .ObserveOn(dispatcher).Subscribe(_ => initialize(mvm.DisplayMatches.Where(dm => dm.MatchDisplayType == DisplayMatch.DisplayType.Assigned).ToArray()));

            ImportStationFile = Command.Create<System.Windows.Window>(_ => true, window =>
            {
                try
                {
                    var ofd = new Microsoft.Win32.OpenFileDialog()
                    {
                        Filter = "Text List (*.csv;*.txt)|*.csv;*.txt|All files (*.*)|*.*",
                        RestoreDirectory = true,
                        Title = "Browse for Station File"
                    };

                    var result = ofd.ShowDialog(window);
                    if (result.HasValue && result.Value)
                    {
                        var path = ofd.FileName;

                        initializeStations(path);
                    }
                }
                catch (Exception ex)
                {
                    System.Windows.MessageBox.Show(window, "Error encountered trying to import station list: " + ex.NewLineDelimitedMessages(),
                        "Error Importing", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
                }
            });

            //Modify ViewModel state when an action is initiated
            Action startAction = () =>
            {
                ErrorMessage = null;
                IsBusy = true;
            };

            //Modify ViewModel state when an action is completed
            Action endAction = () =>
            {
                IsBusy = false;
            };

            //Modify ViewModel state when an action comes back with an exception
            Action<Exception> errorHandler = ex =>
            {
                if (ex.InnerException is ChallongeApiException)
                {
                    var cApiEx = (ChallongeApiException)ex.InnerException;

                    if (cApiEx.Errors != null) ErrorMessage = cApiEx.Errors.Aggregate((one, two) => one + "\r\n" + two);
                    else ErrorMessage = string.Format("Error with ResponseStatus \"{0}\" and StatusCode \"{1}\". {2}", cApiEx.RestResponse.ResponseStatus,
                        cApiEx.RestResponse.StatusCode, cApiEx.RestResponse.ErrorMessage);
                }
                else
                {
                    ErrorMessage = ex.NewLineDelimitedMessages();
                }

                IsBusy = false;
            };

            AutoAssignPending = Command.CreateAsync(() => true, () =>
            {
                Stations.Instance.AssignOpenMatchesToStations(OpenMatches.Select(dm => dm.Match).ToArray());
            }, startAction, endAction, errorHandler);

            CallPendingAnywhere = Command.CreateAsync(() => true, () =>
            {
                var stationsWithoutAssignments = OpenMatches.Where(m => !m.Match.IsMatchInProgress).ToArray();

                foreach (var s in stationsWithoutAssignments) s.Match.AssignPlayersToStation("Any");
            }, startAction, endAction, errorHandler);

            ClearAllAssignments = Command.CreateAsync(() => true, () =>
            {
                var stationsWithAssignments = OpenMatches.Where(m => m.Match.IsMatchInProgress).ToArray();

                foreach (var s in stationsWithAssignments) s.Match.ClearStationAssignment();
            }, startAction, endAction, errorHandler);
        }