Caliburn Micro с NotifyIcon.WPF, несколькими иконками в трее и неудачной привязкой

Я пытаюсь заставить WPF NotifyIcon Hardcodet работать в приложении WPF и получаю странные результаты.

Цель состоит в следующем:

  • MainViewModel получает уведомление от EventAggregator
  • MainViewModel использует ShowBaloonTip для отображения уведомлений

Используемые библиотеки:

  • Caliburn.Micro
  • Hardcodet.NotifyIcon.WPF
  • Autofac
  • Caliburn.Micro.AutofacBootstrap
  • MaterialDesignThemes

Во-первых, я хотел опубликовать реализацию NotifyIcon, которая не имеет реализации BalloonTip. Это прекрасно работает, никаких проблем здесь:

MainView.xaml

<Window.Resources>
    <ContextMenu x:Shared="false" x:Key="MainSysTrayMenu">
        <MenuItem Header="Quick Status" cal:Message.Attach="OpenStatusWindow()" IsEnabled="{Binding Path=CanOpenStatusWindow, Mode=OneWay}" />
        <MenuItem Header="Details" cal:Message.Attach="OpenDetailWindow()" IsEnabled="{Binding Path=CanOpenDetailWindow, Mode=OneWay}" />
        <MenuItem Header="About" cal:Message.Attach="OpenAboutWindow()" IsEnabled="{Binding Path=CanOpenAboutWindow, Mode=OneWay}" />
        <Separator />
        <MenuItem Header="Exit" cal:Message.Attach="ExitApplication()" />
    </ContextMenu>
    <tb:TaskbarIcon x:Key="SystemTrayIcon"
                    IconSource="/Resources/NotifyIcons/Red.ico"
                    ToolTipText="Double-click for window, right-click for menu"
                    cal:Message.Attach="[Event TrayMouseDoubleClick] = [Action OpenStatusWindow]"
                    Visibility="Visible"
                    ContextMenu="{StaticResource MainSysTrayMenu}" >
        <tb:TaskbarIcon.TrayToolTip>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Border HorizontalAlignment="Center" VerticalAlignment="Center"
                        Background="White"
                        BorderBrush="DeepSkyBlue"
                        BorderThickness="2"
                        CornerRadius="4"
                        Opacity="0.95"
                        Width="165"
                        Height="40">
                    <TextBlock Text="{Binding Path=StatusToolTipText, Mode=OneWay}" 
                               HorizontalAlignment="Center"
                               VerticalAlignment="Center"
                               Foreground="Black"
                               FontFamily="{DynamicResource MaterialDesignFont}"
                    />
                </Border>
            </Grid>
        </tb:TaskbarIcon.TrayToolTip>
    </tb:TaskbarIcon>
</Window.Resources>
<Grid>
    <TextBlock>View + ViewModel started from bootstrapper. This should not be visible.</TextBlock>
    <ContentControl >
        <Label x:Name="TestString" Content="Label" HorizontalAlignment="Left" Margin="111,83,0,0" VerticalAlignment="Top"/>
    </ContentControl>
    <ContentControl Content="{StaticResource SystemTrayIcon}" />
</Grid>

MainViewModel

public MainViewModel(IWindowManager windowManager, IEventAggregator eventAggregator, StatusViewModel statusViewModel,
        DetailViewModel detailViewModel, AboutViewModel aboutViewModel)
    {
        _windowManager = windowManager;
        _eventAggregator = eventAggregator;
        _eventAggregator.Subscribe(this);
        _statusViewModel = statusViewModel;
        _detailViewModel = detailViewModel;
        _aboutViewModel = aboutViewModel;
        _statusToolTipText = "SOC: 0% | RTE: 0min";
        LaunchManager();
    }

И вспомогательные функции ViewModel, используемые в MainView

 public bool CanOpenStatusWindow => !_statusViewModel.IsActive;
    public bool CanCloseStatusWindow => _statusViewModel.IsActive;

    public void OpenStatusWindow()
    {
        _windowManager.ShowWindow(_statusViewModel);
        NotifyOfPropertyChange(() => CanOpenStatusWindow);
        NotifyOfPropertyChange(() => CanCloseStatusWindow);

    }

Это дублируется для каждого из трех окон, довольно стандартно.

NotifyIcon "MVVM" реализация

Здесь все становится сложнее. В примере кода из Hardcodet привязка выполняется следующим образом:

<tb:TaskbarIcon IconSource="/Icons/Inactive.ico"
                    ToolTipText="{Binding Timestamp}">
        <tb:TaskbarIcon.TrayPopup >
            <!-- the popup, here a custom user control, will also get the DataContext of the NotifyIcon -->
            <local:ClockPopup Opacity="0.8" />
        </tb:TaskbarIcon.TrayPopup>
    </tb:TaskbarIcon>

Мое намерение состояло в том, чтобы Связать этот TaskbarIcon с NotifyIcon. Мне не удалось заставить реализацию работать со StaticResource, поэтому я перенес весь кусок на страницу MainWindow.xaml:

MainView.xaml

<tb:TaskbarIcon x:Name="NotifyIcon"
                    IconSource="/Resources/NotifyIcons/Red.ico"
                    ToolTipText="Double-click for window, right-click for menu"
                    cal:Message.Attach="[Event TrayMouseDoubleClick] = [Action OpenStatusWindow]"
                    Visibility="Visible">
        <tb:TaskbarIcon.ContextMenu>
            <ContextMenu DataContext="{Binding}">
                <MenuItem Header="Quick Status" cal:Message.Attach="OpenStatusWindow()" IsEnabled="{Binding Path=CanOpenStatusWindow, Mode=OneWay}" />
                <MenuItem Header="Details" cal:Message.Attach="OpenDetailWindow()" IsEnabled="{Binding Path=CanOpenDetailWindow, Mode=OneWay}" />
                <MenuItem Header="About" cal:Message.Attach="OpenAboutWindow()" IsEnabled="{Binding Path=CanOpenAboutWindow, Mode=OneWay}" />
                <Separator />
                <MenuItem Header="Exit" cal:Message.Attach="ExitApplication()" />
            </ContextMenu>
        </tb:TaskbarIcon.ContextMenu>
        <tb:TaskbarIcon.TrayToolTip>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Border HorizontalAlignment="Center" VerticalAlignment="Center"
                        Background="White"
                        BorderBrush="DeepSkyBlue"
                        BorderThickness="2"
                        CornerRadius="4"
                        Opacity="0.95"
                        Width="165"
                        Height="40">
                    <TextBlock Text="{Binding Path=StatusToolTipText, Mode=OneWay}" 
                               HorizontalAlignment="Center"
                               VerticalAlignment="Center"
                               Foreground="Black"
                               FontFamily="{DynamicResource MaterialDesignFont}"
                    />
                </Border>
            </Grid>
        </tb:TaskbarIcon.TrayToolTip>
    </tb:TaskbarIcon>

MainViewModel.xaml

 private NotifyIcon _notifyIcon;

    public NotifyIcon NotifyIcon
    {
        get => _notifyIcon;
        set
        {
            _notifyIcon = value;
            NotifyOfPropertyChange();
        }
    }

    public MainViewModel(IWindowManager windowManager, IEventAggregator eventAggregator,
        StatusViewModel statusViewModel,
        DetailViewModel detailViewModel, AboutViewModel aboutViewModel)
    {
        _notifyIcon = new NotifyIcon();
        _notifyIcon.BalloonTipText = "test";
        _notifyIcon.ShowBalloonTip(3000);
    }

Следующее не сработало, поэтому я попробовал парную реализацию, которую нашел на сайте, но безрезультатно. Эта страница: Как интегрировать WPF NotifyIcon с Caliburn.Micro не работает из-за его старшего возраста (NotifyIcon - это использование, которое они рекомендуют в документации, а не TaskbarIcon). Запуск программы вызвал зацикливание, открывающее множество значков в трее.

Правильное создание экземпляра _notifyIcon с иконкой, контекстным меню и текстом фактически привело к созданию двух панелей задач. Одна с моей хорошей панелью задач и меню, другая с той, что сделана во ViewModel.

Буду признателен за любую помощь, моя единственная цель - сохранить меню, как оно определено в MaterialView.xaml, но иметь возможность запускать уведомления BallonTip для разных состояний соединения и т. Д.

Спасибо за помощь и прочитав все это, я дал ему около 3 дней проб и ошибок, но безрезультатно.

0 ответов

Другие вопросы по тегам