Поведение пункта меню WPF? - PullRequest
0 голосов
/ 09 июля 2020

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

        <Button Grid.Column="0" Margin="5" Content="Select Folder" Style="{StaticResource MaterialDesignRaisedLightButton}">
            <i:Interaction.Behaviors>
                <FolderDialog:FolderDialogBehavior SetterName="FolderName"></FolderDialog:FolderDialogBehavior>
            </i:Interaction.Behaviors>
        </Button>

Теперь я нужно такое поведение (с другим SetterName, конечно) в пункте меню, но у меня нет возможности найти решение для выполнения sh моей задачи, может ли кто-нибудь помочь мне?

<Menu Background="#292A24" Foreground="Yellow" VerticalAlignment="Top" IsMainMenu="True">
    <MenuItem  Header="_File" Height="35">
        <MenuItem Header="Export to csv">
            <MenuItem.Icon>
                <materialDesign:PackIcon Kind="Export" />
            </MenuItem.Icon>
        </MenuItem>
        <MenuItem Header="Exit" InputGestureText="Ctrl+E">
            <MenuItem.Icon>
                <materialDesign:PackIcon Kind="ExitToApp" />
            </MenuItem.Icon>
        </MenuItem>
    </MenuItem>
</Menu>

1 Ответ

0 голосов
/ 09 июля 2020

MenuItem имеет собственное событие Click . Поэтому вам нужно создать новый класс поведения для MenuItem

public class FolderDialogBehavior : Behavior<MenuItem>
{
    public string SetterName { get; set; }

    protected override void OnAttached()
    {
        AssociatedObject.Click += OnClick;
    }
    
    protected override void OnDetaching()
    {
        AssociatedObject.Click -= OnClick;
    }

    private void OnClick(object sender, RoutedEventArgs e)
    {
        var dialog = new FolderBrowserDialog();
        var result = dialog.ShowDialog();
        if (result == DialogResult.OK && AssociatedObject.DataContext != null)
        {
            var propertyInfo = AssociatedObject.DataContext.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)
            .Where(p => p.CanRead && p.CanWrite)
            .Where(p => p.Name.Equals(SetterName))
            .First();

            propertyInfo.SetValue(AssociatedObject.DataContext, dialog.SelectedPath, null);
        }
    }
}

Если вы хотите иметь один класс поведения, вы можете определить подписку через отражение

private RoutedEvent _clickEvent;

protected override void OnAttached()
{
    var memberInfo = AssociatedObject.GetType().GetProperty("ClickEvent");
    if (memberInfo == null)
    {
        return;
    }
    
    _clickEvent = memberInfo.GetValue(AssociatedObject) as RoutedEvent
    if (_clickEvent == null)
    {
        return;
    }
    
    AssociatedObject.AddHandler(_clickEvent, OnClick);
}

protected override void OnDetaching()
{
    if (_clickEvent == null)
    {
        return;
    }
    
    AssociatedObject.RemoveHandler(_clickEvent, OnClick);
}
...