以编程方式显示对话框,然后将其放置在按下对话框的按钮上

时间:2018-07-20 15:13:45

标签: c# wpf mvvm material-design

我目前有一个UserControl View和ViewModel,它们实质上从用户那里获取了一些数据。如果用户没有对系统的访问权限,则应用程序应显示一个弹出框,告知用户此信息-弹出框具有“确定”按钮,然后将其放置该对话框并返回到先前的用户控件。

我也正在使用Material Design来执行此操作,但是根据此处的文档,https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/wiki/Dialogs#dialoghostshow

的实现方式不是很清楚

我的实现如下:

对话框视图:

<UserControl x:Class="GiveUpRegister.Dialogs.MessageBoxView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
             xmlns:system="clr-namespace:System;assembly=mscorlib"
             mc:Ignorable="d"
             Height="auto" Width="auto">

    <materialDesign:Card HorizontalAlignment="Center" materialDesign:ShadowAssist.ShadowDepth="Depth1">
        <DockPanel  Height="auto" Width="250">
            <TextBlock Text="{Binding TxtBlockTitle.Value}" FontWeight="Bold" DockPanel.Dock="Top" Margin="20,20,9,20">Example error title</TextBlock>
            <TextBlock Text="{Binding TxtBlockMessage.Value}" DockPanel.Dock="Top" Margin="20,5,20,10">Some error message.</TextBlock>
            <Button Margin="9,10,9,10" Style="{StaticResource MaterialDesignFlatButton}" DockPanel.Dock="Bottom">
                <Button.CommandParameter>
                    <system:Boolean>True</system:Boolean>
                </Button.CommandParameter>
                OK
            </Button>
        </DockPanel>
    </materialDesign:Card>
</UserControl>

对话框ViewModel:

public class MessageBoxViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;


    private bool _isMessageBoxOpen;
    public bool IsMessageBoxOpen
    {
        get => _isMessageBoxOpen;
        set
        {
            if (_isMessageBoxOpen == value) return;
            _isMessageBoxOpen = value;
            OnPropertyChanged(nameof(IsMessageBoxOpen));
        }
    }

    private object _messageContent;
    public object MessageContent
    {
        get => _messageContent;
        set
        {
            if (_messageContent == value) return;
            _messageContent = value;
            OnPropertyChanged(nameof(MessageContent));
        }
    }


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

如何修改此代码,以便能够从以下代码进行初始化:

StartupViewModel:

private async Task LoadUserDetails()
{
    try
    {
        await Task.Factory.StartNew(() => SystemUserService = SystemUserService.Instance);
        bool hasAccess = SystemUserService.CheckAccessPermission();
        if (hasAccess)
        {
             // Show the dialog box
        }
    }
    catch (Exception ex)
    {
        Logger.SendError("Could not retrieve user details", ex);
    }
}

2 个答案:

答案 0 :(得分:0)

这看起来很有希望。我没有尝试过,但这似乎打开了对话框,然后等待用户单击按钮。我从“关闭策略”网站上的网站上获取了此信息。

var result = await DialogHost.Show(myControl, delegate(object sender, 
DialogOpenedEventArgs args)
{
    args.Session.Close(false);
});

答案 1 :(得分:0)

我找到了一种等待对话框而不阻塞调用UI线程的解决方案。 它远非最佳解决方案,但对我有用。如果有人可以增强它...

您可以尝试以下解决方案: Is there a mean to call Show DialogHost synchronously ?

由代码组成,可以调用以下方法

methodMessageDialog(string message, System.Windows.Forms.MessageBoxButtons messageBoxButtons = System.Windows.Forms.MessageBoxButtons.OK)).

此方法是异步的,正在等待用户按钮回答,它将阻止当前方法而不会阻止UI。