cybertronic
cybertronic

Reputation: 117

UWP GridViewItem shows Classname

I want to implement a GridView in UWP and each Item contains a TextBlock, Checkbox and two ComboBox. What I'm getting at the moment is the Classname instad of the GridViewItem. I think that could be resolved by a DataTemplate maybe?

Xaml File:

<Page.Resources>
    <DataTemplate x:Name="CameraSettingsGridViewTemplate" x:DataType="local:CameraSetting">
        <GridViewItem>
            <StackPanel>
                <TextBlock Text="{x:Bind Property}"/>
                <CheckBox/>
                <ComboBox ItemsSource="{x:Bind Value1}"/>
                <ComboBox ItemsSource="{x:Bind Value2}"/>
            </StackPanel>
        </GridViewItem>
    </DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <GridView Name="CameraSettings" HorizontalAlignment="Left" VerticalAlignment="Top" ItemsSource="{x:Bind CameraSettingsList}"></GridView>
</Grid>

The DataTemplate is an attempt by to solve the problem.

CS File:

  public sealed partial class CameraSettingsPage : Page {
    private ObservableCollection<CameraSetting> cameraSettingsList = new ObservableCollection<CameraSetting>();
    public ObservableCollection<CameraSetting> CameraSettingsList { get { return this.cameraSettingsList; } }
    public CameraSettingsPage() {
        this.InitializeComponent();
        this.cameraSettingsList = new ObservableCollection<CameraSetting>() {
            new CameraSetting() {
                Property = "prop1",
                Auto = new CheckBox(),
                Value1 = new ComboBox() { ItemsSource = new ObservableCollection<string>() { "1", "2" } },
                Value2 = new ComboBox() { ItemsSource = new ObservableCollection<string>() { "a", "b" } }
            }
        };
    }

    private void Page_Loaded(object sender, RoutedEventArgs e) {
    }
}

public class CameraSetting {
    public string Property { get; set; }
    public CheckBox Auto { get; set; }
    public ComboBox Value1 { get; set; }
    public ComboBox Value2 { get; set; }
}

In the constructor i create an example GridViewItem within a ObservableCollection and take this as ItemSource for the GridView.

Upvotes: 0

Views: 204

Answers (1)

Michael Hawker - MSFT
Michael Hawker - MSFT

Reputation: 1580

There's a few things going on here. First, the GridView is showing the name of the class as it's not actually using the data template you've tried to setup.

You need to use x:Key and not x:Name for Resources and then set that resource as the ItemTemplate property for the GridView:

<Page.Resources>
    <DataTemplate x:Key="CameraSettingsGridViewTemplate" x:DataType="local:CameraSetting">
        <GridViewItem>
            <StackPanel>
                <TextBlock Text="{x:Bind Property}"/>
                <CheckBox IsChecked="{x:Bind Auto}"/>
                <ComboBox ItemsSource="{x:Bind Value1}"/>
                <ComboBox ItemsSource="{x:Bind Value2}"/>
            </StackPanel>
        </GridViewItem>
    </DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <GridView Name="CameraSettings" HorizontalAlignment="Left" VerticalAlignment="Top" ItemsSource="{x:Bind CameraSettingsList}" ItemTemplate="{StaticResource CameraSettingsGridViewTemplate}"></GridView>
</Grid>

The second issue, is that you don't recreate controls in your data model. The point of binding and templates is that you can have your basic types in your model (like string option values and booleans), and then bind those to the UI elements that manipulate them. So your data model should look more like this:

public class CameraSetting
{
    public string Property { get; set; }
    public bool Auto { get; set; }
    public List<string> Value1 { get; set; }
    public List<string> Value2 { get; set; }
}

Then you can fill it in, similar to what you had before:

    public ObservableCollection<CameraSetting> CameraSettingsList { get; set; } = new ObservableCollection<CameraSetting>();

    public MainPage()
    {
        this.InitializeComponent();

        this.CameraSettingsList.Add(new CameraSetting()
        {
            Property = "prop1",
            Auto = true,
            Value1 = new List<string>() { "Option 1", "Option 2" },
            Value2 = new List<string>() { "Option 3", "Option 4" },
        });
    }

I'd suggest looking at some of the Binding Samples provided by the platform and there's a good overview of these scenarios and the issue you ran into on the official docs page for binding.

Remember, if you want your data updated on model changes or reflected back to your model on user changes, you'll need to add a Mode=OneWay or Mode=TwoWay to your x:Bind expressions.

Upvotes: 2

Related Questions