Reputation: 197
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
Upvotes: 0
Views: 542
Reputation: 2675
You are adding to an ObservableCollection, however only in the backing field.
private readonly ObservableCollection<SiteIdModel>? _siteIds;
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.
public IEnumerable<SiteIdModel>? SiteIds => _siteIds;
Change your property to an ObservableCollection so that when you populate the list, the view will be notified and update the ItemsSource.
public ObservableCollection<SiteIdModel>? SiteIds => _siteIds;
Upvotes: 0