-
Good evening everyone, <UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:OpenMidiMixer.ViewModels.SplitViewPane"
xmlns:converters="clr-namespace:OpenMidiMixer.Converters"
xmlns:models="clr-namespace:OpenMidiMixer.Models"
xmlns:midiModels="clr-namespace:OpenMidiMixer.Models.MidiInputs"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="OpenMidiMixer.ProfilesPageView"
x:DataType="viewModels:ProfilesPageViewModel">
<Design.DataContext>
<viewModels:ProfilesPageViewModel />
</Design.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0"
Orientation="Vertical"
Spacing="5"
HorizontalAlignment="Stretch"
VerticalAlignment="Top">
<ListBox Padding="0"
ItemsSource="{Binding MidiDevices}"
SelectedItem="{Binding SelectedMidiDevice}">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="{x:Type models:MidiDevice}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
<Border Grid.Column="1"
Background="#ffffff"
Padding="10">
<ScrollViewer>
<StackPanel Orientation="Vertical"
Spacing="10">
<TextBlock Text="Faders"
FontSize="18"
FontWeight="Bold" />
<!-- HERE IT WORKS -->
<ComboBox Width="150"
HorizontalContentAlignment="Stretch"
HorizontalAlignment="Stretch"
ItemsSource="{Binding SessionList}" />
<!-- HERE IT WORKS -->
<ItemsControl ItemsSource="{Binding SelectedMidiDevice.Faders}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="midiModels:Fader">
<StackPanel Orientation="Horizontal" Spacing="5">
<TextBlock Text="{Binding Name}"
VerticalAlignment="Center"
Foreground="#222222"/>
<!-- HERE IT DOES NOT WORK -->
<ComboBox Width="150"
HorizontalContentAlignment="Stretch"
HorizontalAlignment="Stretch"
ItemsSource="{Binding $parent[viewModels:ProfilesPageViewModel].SessionList}" />
<!-- HERE IT DOES NOT WORK -->
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
</Border>
</Grid>
</UserControl> Heres my ViewModel ( using Avalonia.Interactivity;
using CommunityToolkit.Mvvm.ComponentModel;
using NAudio.Midi;
using OpenMidiMixer.Models;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Timers;
namespace OpenMidiMixer.ViewModels.SplitViewPane
{
public partial class ProfilesPageViewModel : ViewModelBase
{
[ObservableProperty]
private ObservableCollection<MidiDevice> _midiDevices = [];
[ObservableProperty]
private MidiDevice? _selectedMidiDevice;
[ObservableProperty]
private ObservableCollection<string> _sessionList = [];
private readonly List<string> _supportedDevices =
[
"X-Touch-Ext", "X-Touch-Mini"
];
private Timer? _deviceCheckTimer;
public void OnLoaded(object? sender, RoutedEventArgs e)
{
LoadMidiDevices();
SessionList.Add("Session1");
SessionList.Add("Session2");
SessionList.Add("Session3");
SessionList.Add("Session4");
SessionList.Add("Session5");
_deviceCheckTimer = new Timer(1000);
_deviceCheckTimer.Elapsed += CheckForMidiDeviceChanges;
_deviceCheckTimer.Start();
}
public void OnUnloaded(object? sender, RoutedEventArgs e)
{
if (_deviceCheckTimer == null)
return;
_deviceCheckTimer.Stop();
_deviceCheckTimer.Dispose();
}
private void LoadMidiDevices()
{
int deviceCount = MidiIn.NumberOfDevices;
for (int i = 0; i < deviceCount; i++)
{
MidiInCapabilities deviceInfo = MidiIn.DeviceInfo(i);
if (!_supportedDevices.Contains(deviceInfo.ProductName))
continue;
MidiDevice midiDevice = new()
{
ProductId = deviceInfo.ProductId,
ProductName = deviceInfo.ProductName,
Manufacturer = deviceInfo.Manufacturer,
IsConnected = true,
};
midiDevice.InitializeControls();
MidiDevices.Add(midiDevice);
}
}
private void CheckForMidiDeviceChanges(object? sender, ElapsedEventArgs e)
{
int currentDeviceCount = MidiIn.NumberOfDevices;
List<MidiDevice> currentDevices = [];
for (int i = 0; i < currentDeviceCount; i++)
{
MidiInCapabilities deviceInfo = MidiIn.DeviceInfo(i);
if (!_supportedDevices.Contains(deviceInfo.ProductName))
continue;
currentDevices.Add(new MidiDevice()
{
ProductId = deviceInfo.ProductId,
ProductName = deviceInfo.ProductName,
Manufacturer = deviceInfo.Manufacturer,
IsConnected = true,
});
}
List<MidiDevice> devicesToRemove = MidiDevices
.Where(device => !currentDevices
.Any(d => d.ProductId == device.ProductId)
)
.ToList();
List<MidiDevice> devicesToAdd = currentDevices
.Where(device => !MidiDevices
.Any(d => d.ProductId == device.ProductId)
)
.ToList();
foreach (MidiDevice device in devicesToRemove)
{
MidiDevices.Remove(device);
}
foreach (MidiDevice device in devicesToAdd)
{
MidiDevices.Add(device);
}
}
}
} I'm supposing that the reason is that I've losed the DataContext. I've tried to use ancestors like in WPF but found out that this way is different in XPF. If somebody have a solution for issue ^^ PS: Sorry in advance if my English is bad |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
This won't work, because the $parent binding selects controls, not their DataContext. You'll need to change it to |
Beta Was this translation helpful? Give feedback.
ItemsSource="{Binding $parent[viewModels:ProfilesPageViewModel].SessionList}"
This won't work, because the $parent binding selects controls, not their DataContext. You'll need to change it to
ItemsSource="{Binding $parent[ProfilesPageView].((viewModels:ProfilesPageViewModel)DataContext).SessionList}"
or similar (fixing namespaces, etc), selecting a control and then casting its DataContext to the appropriate type.