C
C#2mo ago
Mekasu0124

Accessing Function from Nested UI File - Avalonia

Ok so I have the following file structure for my Avalonia MVVM project
root/
|
| - Views/
| | - MenuBar/
| | | - FileMenu.axaml
| | - MainWindowView.axaml
root/
|
| - Views/
| | - MenuBar/
| | | - FileMenu.axaml
| | - MainWindowView.axaml
In my FileMenu.axaml file I have a menu option
<MenuItem Header="_Exit" />
<MenuItem Header="_Exit" />
I know to bind it to a command I would do
<MenuItem Header="_Exit" Command="{Binding Exit}" />
<MenuItem Header="_Exit" Command="{Binding Exit}" />
however, the exit function is in my MainWindowViewModel. So I have two questions. 1. Is it ok if I put the exit command in the FileMenu.axaml.cs file to exit the program? 2. If not, do I create a ViewModel file in the same directory as the FileMenu.axaml file and then call that code behind for all of my nested menu options? either way, if it's ok to stay in the MainWindowViewModel, then how do I properly bind to it? I remember in a Todo tutorial they did something like a this.Something.bind.x or something like that. Let me see if I can find it
12 Replies
Mekasu0124
Mekasu01242mo ago
this is it
<Button Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
Command="{Binding $parent[Window].DataContext.AddItem}"
Content="New Item"/>
<Button Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
Command="{Binding $parent[Window].DataContext.AddItem}"
Content="New Item"/>
I'm going to try that that didn't work, but basically I've got this menu bar
<DockPanel Grid.Row="0">
<uc:FileMenu />
<uc:EditMenu />
<uc:SettingsMenu />
<uc:HelpMenu />
</DockPanel>
<DockPanel Grid.Row="0">
<uc:FileMenu />
<uc:EditMenu />
<uc:SettingsMenu />
<uc:HelpMenu />
</DockPanel>
in my MainWindowView.axaml file which is a Window not a UserControl. I then have in my views folder a MenuBar folder that holds each menu bar item as a UserControl. In the /Views/MenuBar/FileMenu.axaml file I'm trying to bind the Exit menu item to the Exit function in the /ViewModels/MainWindowViewModel.cs file or put the exit command where it should go for a bound command to a menu bar item like I've used it......
Denis
Denis2mo ago
Alternatively you could use messaging. If you are using community toolkit, then WeakReferenceMessenger allows you to send a message that any listener across your app can pickup and handle Eg, your close command will send the close messages,.and the main window will handle it
Mekasu0124
Mekasu01242mo ago
ohhhh like I did here
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;

namespace Diary.ViewModels;

public partial class MainViewModel : ViewModelBase
{
[ObservableProperty] private string? _loggedInUserName;

public MainViewModel()
{
Messenger.Register<UserLoggedInMessage>(this, UserLoggedIn);
}

[RelayCommand] public async Task Logout()
{
await Task.Delay(50);
Messenger.Send(new UserLoggedOutMessage());
}

private void UserLoggedIn(object recipient, UserLoggedInMessage message)
{
LoggedInUserName = message.user.Username;
}
}
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;

namespace Diary.ViewModels;

public partial class MainViewModel : ViewModelBase
{
[ObservableProperty] private string? _loggedInUserName;

public MainViewModel()
{
Messenger.Register<UserLoggedInMessage>(this, UserLoggedIn);
}

[RelayCommand] public async Task Logout()
{
await Task.Delay(50);
Messenger.Send(new UserLoggedOutMessage());
}

private void UserLoggedIn(object recipient, UserLoggedInMessage message)
{
LoggedInUserName = message.user.Username;
}
}
Mekasu0124
Mekasu01242mo ago
and the UserLoggedInMessage is defined in the MainWindowViewModel.cs file. but my other issue that may not even be an issue is that it's separate projects. One so far is console which is just a backend service and the other is the desktop app. Will it matter if I change the desktop app from Avalonia.ReactiveUI to CommunityToolkit.MVVM with my project structure looking like
TeachersAide/
- src/
- AddressBook/ (console)
- GradeBook/
- Assets/
- ...
TeachersAide/
- src/
- AddressBook/ (console)
- GradeBook/
- Assets/
- ...
No description
Denis
Denis2mo ago
Reactive UI has its own messaging framework - https://www.reactiveui.net/docs/handbook/message-bus.html You can always create a third project to share the message classes
Mekasu0124
Mekasu01242mo ago
with this part being mentioned of creating a messaging project, with having multiple projects in my src/ folder, when I go to package my project down to a .exe, how do I get the thing to recognize that package I want the .exe to always launch from? Example: If I have a Diary.Desktop, Diary.Infrastructure, and Diary.Common. When I package the project down to an executable, how do I get the .exe to know that Diary.Desktop is the source to launch from each time and not Common or Infrastructure?
Denis
Denis2mo ago
Well the infrastructure and common are library projects, right? So it'll know automatically to start the executable application which is your Desktop project
Mekasu0124
Mekasu01242mo ago
I'm not sure if I set them up right. I right clicked the top TeachersAide and clicked New Project > Console > named it and created it
Denis
Denis5w ago
An executable project usually has a Program.cs You can always right click and view properties of a project. Or double click a project to view itd XML definition
Mekasu0124
Mekasu01245w ago
ok so if I don't need a console project for let's say my Infrastructure project which is what handles all database executions and such, how and what would I make instead?
Denis
Denis5w ago
A class library a non-executable project
Mekasu0124
Mekasu01244w ago
ah. thank you!