• XAML: 在 MVVM 模式中,关于绑定的几处技巧


        以下会提到三个绑定的技巧,分别是

    • 在 ListView 中为 ListViewItem 的 MenuFlyout 绑定 Command;
    • 在 ListView 的 事件中绑定所选择项目,即其 SelectedItem属性;
    • 处理文本控件与数值属性绑定中默认值0的问题;

    一、在 ListView 中为列表项的 MenuFlyout 绑定 Command;

        当我们为 ListView 编写了 DataTemplate,并在其中加入了 MenuFlyout 时,而且 MenuFlyoutItem 需要绑定 ViewModel 中的 XXXCommand 属性,代码类似如下:

        <Page.Resources>
            <DataTemplate x:Key="CategoryItemTemplate">
                <Grid Holding="Grid_Holding">
                    <FlyoutBase.AttachedFlyout>
                        <MenuFlyout>
                            <MenuFlyoutItem x:Uid="MenuItem_Edit" Command="{Binding EditCategoryCommand}" CommandParameter="{Binding}"/>
                            <MenuFlyoutItem x:Uid="MenuItem_Delete" Command="{Binding DeleteCategoryCommand}" CommandParameter="{Binding}"/>
                        </MenuFlyout>
                    </FlyoutBase.AttachedFlyout>
                    <TextBlock Text="{Binding Name}" FontSize="24" Margin="0,5" />
                </Grid>
            </DataTemplate>
        </Page.Resources>

       这时,如果运行,你会发现,点击 MenuFlyoutItem 时,并不会触发相应的方法,也就是说这样的绑定是无效的;一个可取的解决方案是,将 ViewModel 作为资源放到 XAML 中,然后,更改 Command 的值为:

    Command="{Binding EditCategoryCommand,Source={StaticResource viewModelName}}"

       这样可以解决问题,但存在两个问题:1, 这个 viewModel 是一个新创建的对象,而与你实际使用的 ViewModel 对象不是一个,所以;2, ViewModel 必须有无参数的构造函数(其实这与第一个问题是相关联的)。

       在网上查了一些资料之后,终于找到一个较完美的解决方案,如下:修改 Command 的值为:

    Command="{Binding DataContext.EditCategoryCommand,ElementName=pageCategory}"

       其中,pageCategory 是 Page 的 x:Name 值;这样 MenuFlyoutItem 就可以正确响应你的操作了。至于修改之后的 Command 的属性值,相信你一看就明白,在此不再赘述。

    二、在 ListView 的 事件中绑定所选择项目,即其 SelectedItem属性

       先看代码,注意粗体部分:

                <ListView x:Name="listCategory" ItemsSource="{Binding Categories}" ItemContainerStyle="{StaticResource StretchListViewItemStyle}">
                    <Interactivity:Interaction.Behaviors>
                        <Core:EventTriggerBehavior EventName="SelectionChanged">
                            <Core:InvokeCommandAction Command="{Binding CategorySelectedCommand}" CommandParameter="{Binding ElementName=listCategory,Path=SelectedItem}" />
                        </Core:EventTriggerBehavior>
                    </Interactivity:Interaction.Behaviors>
                    ...

       这个其实很简单,之所以记下来,是因为我原先走了一点弯路,之前没有写 Path,然后到 Command 所指向的方法中,把 parameter 再转 ListView 对象,再获取它的 SelectedItem 属性;现在看来,的确是多走了一段弯路;究其原因,实在是因为自己对 WPF 中绑定还不够熟悉。

    三、处理文本控件与数值属性绑定中默认值 0 的问题

       当把文本框的 Text 属性绑定到一个数值属性时,如果该数值属性没有赋值,那么,运行时,它的默认值 0 会显示到文本框中,如果不希望显示默认值 0,则可以使用一个 Converter 来解决,代码如下:

        public class PriceCheckConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, string language)
            {
                float result = (float)value;
                if (result <= 0)
                {
                    return string.Empty;
                }
                else
                {
                    return result.ToString();
                }
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, string language)
            {
                return value;
            }
        }

       而在绑定中,则直接指定该 Converter 即可,代码如下:

    Text="{Binding Bill.Price,Mode=TwoWay,Converter={StaticResource PriceCheckConverter}}"

       如果你有更好的方法,请回复。

    参考资料:

    Windows 8.1 Command Binding in a DataTemplate

    How to implement a navigation button in shared application resources?

    (以上两个链接均是针对第一个问题)

    作者:WPInfo

    本文系作者原创,欢迎转载;如需转载,请注明出处。

    公众号:.NET之窗 (WinDotNET),更多原创、优质技术文章,欢迎扫码关注。

  • 相关阅读:
    什么是守护线程?
    如何优雅地停止一个线程?
    如何创建、启动 Java 线程?
    什么是线程?什么是进程?为什么要有线程?有什么关系与区别?
    并行是什么意思?与并发的区别是什么?
    并发编程的缺点?
    BZOJ_3058_四叶草魔杖_kruscal+状压DP
    BZOJ_3476_[Usaco2014 Mar]The Lazy Cow_扫描线+切比雪夫距离
    BZOJ_1511_[POI2006]OKR-Periods of Words_KMP
    BZOJ_3479_[Usaco2014 Mar]Watering the Fields_Prim
  • 原文地址:https://www.cnblogs.com/wpinfo/p/4599276.html
Copyright © 2020-2023  润新知