【问题标题】:UWP Gridview binding to View ModelUWP Gridview 绑定到视图模型
【发布时间】:2017-07-04 00:28:26
【问题描述】:

我在 UserControl 中使用 GridView 来显示允许选择课程的 5 x 4 正方形图形按钮。

这是我正在升级到 Windows 10 UWP 的 Windows 8.1 应用商店应用程序。

我之前使用 Tap 和 Right-Tap 动作来选择一课或激活 CommandBar 以通过 SelectionChanged 事件为一课执行相关动作。但是,现在交互在 Windows 10 下的工作方式已经发生了变化,我无法通过将 SelectedItem 绑定到视图模型中选定的 LessonButton 来让 Gridview 正常工作,也无法使用用于此类目的的 SelectionChanged 和 ItemClick 事件。 Gridview 选择行为不起作用,因为一旦选择了一个项目,它就永远不会取消选择。所以最后,我采取了不同的策略,我正在尝试为 Gridview 项目的 Tap 和 Right-Tap 事件。但是问题是,无论我采用哪种方式,我都无法让 Binding 正常工作。

所以我有一个名为 LessonButton 的对象:

public class LessonButton : INotifyPropertyChanged
{
    //public LessonButton() { }
    public LessonButton(SolidColorBrush inBackground, bool inComplete, double inHeight, int inNumber, bool inSelected, bool inStarted,
        Status inState, double inWidth)
    {
        ...
        Started = inStarted;
        ...
    }
    ...
    private bool _started;
    public bool Started
    {
        get { return _started; }
        set { if (_started != value) { _started = value; OnPropertyChanged(); } }
    }
    ...
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

它被添加到 View Model 中的可观察集合中:

public class LessonsViewModel : INotifyPropertyChanged
{
    public ObservableCollection<LessonButton> Lessons { get; } = new ObservableCollection<LessonButton>();

    private LessonButton _selectedLessonButton;

    public LessonButton SelectedLessonButton
    {
        get { return _selectedLessonButton; }
        set { if (_selectedLessonButton != value) { _selectedLessonButton = value; OnPropertyChanged(); } }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
} 

在用户控件中,我将 DataContext 设置为:

<UserControl.DataContext>
    <classes:LessonsViewModel/>
</UserControl.DataContext>

..然后我将 GridView 定义为:

        <GridView x:Name="LessonGridView" ItemContainerStyle="{StaticResource GridViewItemStyle}" ItemsSource="{Binding Lessons}"
              SelectionMode="Single" IsItemClickEnabled="False" SelectedItem="{Binding Path=SelectedLessonButton, Mode=TwoWay}">
        <GridView.ItemsPanel>
            <ItemsPanelTemplate>
                <VariableSizedWrapGrid HorizontalChildrenAlignment="Left" MaximumRowsOrColumns="5" Orientation="Horizontal" VerticalChildrenAlignment="Top"/>
            </ItemsPanelTemplate>
        </GridView.ItemsPanel>
    </GridView>

使用 ControlTemplate 中定义的 GridView 项目格式作为 GridViewItemStyle 的一部分。

我尝试使用 Binding 和 xBind 以各种方式访问​​ LessonButton 变量,但只能使用此 XAML 让程序与 ControlTemplate 一起运行:

    <Image Grid.Row="1" Grid.Column="1" Width="{StaticResource BadgeSize}" 
    Height="{StaticResource BadgeSize}" HorizontalAlignment="Right" VerticalAlignment="Top"
    Opacity="{Binding Started, Converter={StaticResource OpacityConverterTrueValueIsVisible}}"
    Source="/Assets/SelectionButtonGroup/square310x310logobw.png" Stretch="Uniform"/>

Converter 仅根据 bool Started 的值返回 1 或 0。

虽然此代码有效,但它不正确,Visual Studio 报告未知错误并声明它找不到 Started 属性。事实上,它找不到 LessonButton 的任何属性,我也找不到正确的语法来公开它们,即使使用 x:Bind 代码,例如:

{x:Bind LessonViewModel.Lessons.LessonButton.Selected}

..或其版本,使用强制转换等。

我正在使用 Visual Studio 2017 Enterprise,它会报告上述错误并在整个 ControlTemplate 上显示波浪线,其中出现错误,它无法找到与此代码无关的另一个 Converter 工件。它本身,我觉得非常烦人。是我还是 VS 中的 XAML Intellisence 看起来非常不稳定,因为如果它无法识别真正错误的根本原因,它会放弃并报告错误错误?

理想情况下,我希望 Gridview SelectedItem 与 ViewModel 绑定。但即使尝试通过 Tap 事件执行操作,我也无法获得绑定以在 ControlTemplate XAML 中正确公开 LessonButton 属性。

任何帮助将不胜感激。

【问题讨论】:

    标签: c# xaml gridview


    【解决方案1】:

    您不应该使用ItemContainerStyle 将您的LessonButton 变量绑定到。 ItemContainerStyle 用于使用选择标记、悬停和按下状态等设置项目的样式。

    您应该改用 DataTemplate 存储在您的 UserControl 的资源中,如下所示:

    <Grid>
      <Grid.Resources>
        <DataTemplate x:Name="GridViewTemplate">
          <TextBlock Text="{Binding LessonName}">
        </DataTemplate>
      </StackPanel.Resources>
      <GridView x:Name="GridView"
                ItemsSource="{Binding Lessons}"
                ItemTemplate="{StaticResource GridViewTemplate}">
      </GridView>
    </Grid>
    

    然后为您的DataTemplate 命名(在“GridViewTemplate”上方)并将其设置为您的GridViewItemTemplate

    【讨论】:

    • 您好 jsmyth886,感谢您的快速回复。我按照您的建议调整了代码,并创建了一个新的缩减项目,只有最低限度。这是我从 Dropbox 共享的文件的链接 - dropbox.com/s/jq4126ca2e9gzuz/GridViewDebug.zip?dl=0
    • 您可以看到 VS 的行为正如我所描述的那样运行良好,但 XAML Intellisense 仍然报告它找不到 Selected 属性。我所有的研究都表明代码是正确的,但 VS 仍然报告错误。这可能是 VS 中的错误吗?
    • @PythonesqueSpam 非常有趣我不知道为什么智能感知显示这么多错误但仍然运行良好。把这个贴在 MSDN 上可能会有用,看看你能不能从微软那里得到一些帮助
    • 根据您的建议,我已在 MSDN 上发布 - social.msdn.microsoft.com/Forums/vstudio/en-US/… ..希望得到答案..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-20
    • 1970-01-01
    • 2018-05-25
    • 1970-01-01
    • 2023-03-06
    • 2012-07-31
    • 1970-01-01
    相关资源
    最近更新 更多