I have a combo box on a form that is not being populated, even though when I step through the code, I can see that the values have been assigned to the properties. What am I missing here:
.axaml
<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:vm="clr-namespace:TAStagingApp.ViewModels.Implementations.Terminal;assembly=TAStagingApp.ViewModels"
xmlns:terminal="clr-namespace:TAStagingApp.Views.Terminal;assembly=TAStagingApp"
mc:Ignorable="d"
d:DesignWidth="800"
d:DesignHeight="450"
x:DataType="vm:TerminalConfigureViewModel"
x:Class="TAStagingApp.Views.Terminal.TerminalConfigureView"
Background="{StaticResource TABackgroundColor}">
<UserControl.DataContext>
<vm:TerminalConfigureViewModel />
</UserControl.DataContext>
<UserControl.Styles>
<StyleInclude Source="/Styles/ConfigureViews/Configure.ComboBoxes.axaml" />
<StyleInclude Source="/Styles/ConfigureViews/Configure.LabelStyles.axaml" />
<StyleInclude Source="/Styles/ConfigureViews/Configure.StackPanels.axaml" />
</UserControl.Styles>
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceInclude Source="/Styles/ConfigureViews/Configure.Buttons.axaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid
ColumnDefinitions="*, Auto, Auto, *"
RowDefinitions="*, Auto, Auto, Auto, Auto, *"
Classes="StagingGrid">
<!-- Instructions Row -->
<Label
Classes="ConfigureH1"
Grid.Row="1"
Grid.Column="1"
Grid.ColumnSpan="2">
PLEASE ENTER THE FOLLOWING INFORMATION:
</Label>
<!-- Site ID Row -->
<StackPanel
Grid.Row="2"
Grid.Column="1"
Classes="ServerConfigureStackPanel">
<Label
Classes="ConfigureH2">
SITE ID:
</Label>
<ComboBox
Classes="Configure"
Width="296"
Margin="10 5 5 10"
ItemsSource="{Binding SiteIds}"
SelectedItem="{Binding SiteId, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate>
<ComboBoxItem>
<ComboBoxItem.Content>
<Binding Path="SiteId" />
</ComboBoxItem.Content>
</ComboBoxItem>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
<!-- Device -->
<StackPanel
Grid.Row="3"
Grid.Column="1"
Classes="ServerConfigureStackPanel">
<Label
Classes="ConfigureH2">
DEVICE:
</Label>
<ComboBox
Classes="Configure"
Width="296"
Margin="10 5 5 10"
ItemsSource="{Binding Terminals}"
SelectedItem="{Binding Terminal}">
<ComboBox.ItemTemplate>
<DataTemplate>
<ComboBoxItem>
<ComboBoxItem.Content>
<Binding Path="DeviceName" />
</ComboBoxItem.Content>
</ComboBoxItem>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
<!-- Configure Button -->
<Button
Grid.Column="1"
Grid.Row="4"
Grid.ColumnSpan="2"
Command="{Binding Configure}"
Theme="{DynamicResource ConfigureButton}">
CONFIGURE
</Button>
</Grid>
</UserControl>
C#
namespace TAStagingApp.ViewModels.Implementations.Terminal;
public class TerminalConfigureViewModel : ViewModelBase, IConfigureViewModel
{
private readonly ObservableCollection<SiteIdModel>? _siteIds;
private readonly ObservableCollection<TerminalModel>? _terminals;
private readonly IMediator? _mediator;
private SiteIdModel? _siteId;
private TerminalModel? _terminal;
public TerminalConfigureViewModel(IMediator mediator)
{
_mediator = mediator;
_siteIds = [];
_terminals = [];
}
public TerminalConfigureViewModel()
{
}
public IEnumerable<SiteIdModel>? SiteIds => _siteIds;
public IEnumerable<TerminalModel>? Terminals => _terminals;
public SiteIdModel? SiteId
{
get => _siteId;
set
{
_siteId = value;
this.RaiseAndSetIfChanged(ref _siteId, value);
this.RaisePropertyChanged(nameof(Terminals));
if (_siteId == value)
{
_terminals!.Clear();
GetNewTerminalList();
}
}
}
[Reactive]
public TerminalModel? Terminal { get; set; }
public async void Activate()
{
_siteIds!.AddRange(await GetSiteIdListAsync());
_siteId = SiteId = _siteIds![0];
_terminal = Terminal = _terminals![0];
}
public void Configure()
{
throw new NotImplementedException();
}
private async void GetNewTerminalList()
{
var query = new ListDevicesBySiteIdQuery(_siteId!.SiteId!);
var queryResult = await _mediator!.Send(query);
var terminals = new List<TerminalModel>();
foreach (var result in queryResult.Value)
{
terminals.Add(new TerminalModel(
result.Site!.SiteNumber,
result.TerminalName));
}
_terminals!.AddRange(terminals);
_terminal = Terminal = _terminals![0];
}
private async Task<List<SiteIdModel>> GetSiteIdListAsync()
{
var query = new ListSitesQuery();
var queryResult = await _mediator!.Send(query);
var siteIds = new List<SiteIdModel>();
foreach (var result in queryResult.Value)
{
siteIds.Add(new SiteIdModel(result.SiteNumber));
}
return [.. siteIds.OrderBy(x => x.SiteId)];
}
}
If I step through the view model, I can see that all of the properties are populated correctly. But nothing shows up in the UI.
Thanks
You are adding to an ObservableCollection, however only in the backing field.
However the accessible property is an IEnumerable. An IEnumerable might be an ObservableCollection, but it can also be a simple array and several other things. The view can only access members defined in IEnumerable.
Change your property to an ObservableCollection so that when you populate the list, the view will be notified and update the ItemsSource.