я только что удалось получить мое WPF окно пользовательских сообщений, чтобы работать, как я намеревался это ... почти:Как реализовать команды в пользовательском элементе управления, не прибегая к обратному коду?
MessageWindow window;
public void MessageBox()
{
var messageViewModel = new MessageViewModel("Message Title",
"This message is showing up because of WPF databinding with ViewModel. Yay!",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec fermentum elit non dui sollicitudin convallis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Integer sed elit magna, non dignissim est. Morbi sed risus id mi pretium facilisis nec non purus. Cras mattis leo sapien. Mauris at erat sapien, vitae commodo turpis. Nam et dui quis mauris mattis volutpat. Donec risus purus, aliquam ut venenatis id, varius vel mauris.");
var viewModel = new MessageWindowViewModel(messageViewModel, BottomPanelButtons.YesNoCancel);
window = new MessageWindow(viewModel);
viewModel.MessageWindowClosing += viewModel_MessageWindowClosing;
window.ShowDialog();
var result = viewModel.DialogResult;
System.Windows.MessageBox.Show(string.Format("result is {0}", result));
}
void viewModel_MessageWindowClosing(object sender, EventArgs e)
{
window.Close();
}
Под капотом есть пользовательский элемент управления «BottomPanel», который просто создает кучу кнопок с их Атрибут «Видимость», управляемый MessageWindowViewModel (через атрибуты свойств, такие как «IsOkButtonVisible», сам определяется значением перечисления «BottomPanelButtons», переданным конструктору viewmodel).
В то время как это соответствует моему требованию иметь возможность отображения окна сообщений с разборными деталями и настраиваемого набора кнопок внизу, я разочарован тем, как мне пришлось поместить все функциональные возможности, которые я изначально хотел получить в BottomPanel контроль (или, вернее, в его ViewModel), в классе MessageWindowViewModel:
public MessageWindowViewModel(MessageViewModel messageViewModel, BottomPanelButtons buttons)
{
_messageViewModel = messageViewModel;
_abortCommand = new DelegateCommand(ExecuteAbortCommand, CanExecuteAbortCommand);
_applyCommand = new DelegateCommand(ExecuteApplyCommand, CanExecuteApplyCommand);
_cancelCommand = new DelegateCommand(ExecuteCancelCommand, CanExecuteCancelCommand);
_closeCommand = new DelegateCommand(ExecuteCloseCommand, CanExecuteCloseCommand);
_ignoreCommand = new DelegateCommand(ExecuteIgnoreCommand, CanExecuteIgnoreCommand);
_noCommand = new DelegateCommand(ExecuteNoCommand, CanExecuteNoCommand);
_okCommand = new DelegateCommand(ExecuteOkCommand, CanExecuteOkCommand);
_retryCommand = new DelegateCommand(ExecuteRetryCommand, CanExecuteRetryCommand);
_yesCommand = new DelegateCommand(ExecuteYesCommand, CanExecuteYesCommand);
Buttons = buttons;
}
/// <summary>
/// Gets/sets a value that determines what buttons appear in the bottom panel.
/// </summary>
public BottomPanelButtons Buttons { get; set; }
public bool IsCloseButtonVisible { get { return Buttons == BottomPanelButtons.ApplyClose || Buttons == BottomPanelButtons.Close; } }
public bool IsOkButtonVisible { get { return Buttons == BottomPanelButtons.Ok || Buttons == BottomPanelButtons.OkCancel; } }
public bool IsCancelButtonVisible { get { return Buttons == BottomPanelButtons.OkCancel || Buttons == BottomPanelButtons.RetryCancel || Buttons == BottomPanelButtons.YesNoCancel; } }
public bool IsYesButtonVisible { get { return Buttons == BottomPanelButtons.YesNo || Buttons == BottomPanelButtons.YesNoCancel; } }
public bool IsNoButtonVisible { get { return IsYesButtonVisible; } }
public bool IsApplyButtonVisible { get { return Buttons == BottomPanelButtons.ApplyClose; } }
public bool IsAbortButtonVisible { get { return Buttons == BottomPanelButtons.AbortRetryIgnore; } }
public bool IsRetryButtonVisible { get { return Buttons == BottomPanelButtons.AbortRetryIgnore || Buttons == BottomPanelButtons.RetryCancel; } }
public bool IsIgnoreButtonVisible { get { return Buttons == BottomPanelButtons.AbortRetryIgnore; } }
public ICommand AbortCommand { get { return _abortCommand; } }
public ICommand ApplyCommand { get { return _applyCommand; } }
public ICommand CancelCommand { get { return _cancelCommand; } }
public ICommand CloseCommand { get { return _closeCommand; } }
public ICommand IgnoreCommand { get { return _ignoreCommand; } }
public ICommand NoCommand { get { return _noCommand; } }
public ICommand OkCommand { get { return _okCommand; } }
public ICommand RetryCommand { get { return _retryCommand; } }
public ICommand YesCommand { get { return _yesCommand; } }
public string AbortButtonText { get { return resx.AbortButtonText; } }
public string ApplyButtonText { get { return resx.ApplyButtonText; } }
public string CancelButtonText { get { return resx.CancelButtonText; } }
public string CloseButtonText { get { return resx.CloseButtonText; } }
public string IgnoreButtonText { get { return resx.IgnoreButtonText; } }
public string NoButtonText { get { return resx.NoButtonText; } }
public string OkButtonText { get { return resx.OkButtonText; } }
public string RetryButtonText { get { return resx.RetryButtonText; } }
public string YesButtonText { get { return resx.YesButtonText; } }
private ICommand _abortCommand;
private ICommand _applyCommand;
private ICommand _cancelCommand;
private ICommand _closeCommand;
private ICommand _ignoreCommand;
private ICommand _noCommand;
private ICommand _okCommand;
private ICommand _retryCommand;
private ICommand _yesCommand;
и есть еще код ниже - фактические Execute
и CanExecute
обработчики, которые все делают то же самое: установить DialogResult
имущество и поднять MessageWindowClosing
события:
private void ExecuteCloseCommand(object commandArgs)
{
DialogResult = DialogResult.Close;
if (MessageWindowClosing != null) MessageWindowClosing(this, EventArgs.Empty);
}
private bool CanExecuteCloseCommand(object commandArgs)
{
return true;
}
Теперь это работает, но я нахожу его уродливым. Я имею в виду, что я хотел бы иметь, это класс BottomPanelViewModel, содержащий все функции BottomPanel. Единственное, что мне нравится в этом, это то, что у меня нет кода (кроме конструктора, который принимает MessageViewModel в классе MessageView, устанавливая свойство DataContext).
Итак, вопрос заключается в следующем: можно ли реорганизовать этот код, чтобы я мог использовать многократно используемый элемент управления BottomPanel, который встраивает его функциональность в свою собственную модель просмотра и имеет свои собственные команды? Идея состоит в том, чтобы иметь команды в элементе управления BottomPanel и обработчики в ViewModel содержащего окна ... или это слишком много растягивается?
Я пробовал много вещей (свойства зависимостей, статические команды, ...), но теперь у меня есть единственный способ заставить его работать без кода. Я уверен, что есть лучший, более сфокусированный способ делать вещи - пожалуйста, извините мой WPF-noobness, это окно «окно сообщения» - это мой WPF «Hello World!». первый проект когда-либо ...
Вы считаете, что вы ищете термин «RoutedCommand»; эта ссылка может помочь: http://joshsmithonwpf.wordpress.com/2008/03/18/understanding-routed-commands/ – JerKimball
Если вы помечаете свое сообщение как 'C#', вы получите подсветку синтаксиса, и вы, вероятно, получите больше ответов. –
Кроме того, этот вопрос может быть лучше подходит для [Code Review] (http://codereview.stackexchange.com/) –