现操-week3

作业感想

  • 感觉这个需求给的很没逻辑,做起来的时候感觉按组件分,之后再分出一些大的逻辑会更有条理..
  • 搜索要多加关键词,UWP是肯定要加的,尽量多加可能涉及的关键词,找出来的结果才准
  • 看代码善用ctrl+F,只看需要的部分,看XAML看绑定逻辑&逻辑上下文,看cs看具体实现&嵌套
  • 看英文别太着急,认认真真看才行

作业需求及实现方法

收尾时发现一个BUG:

在主页面修改,点击appaddbarbutton之后什么都不做直接返回,会返回到初始状态的Mainpage。
搜索:

uwp onbackrequested parameter

得到完美解答!
http://edi.wang/post/2016/2/1/windows-10-uwp-back-button-tricks

后退时候保持前一个页面的状态

如果你前一个页面是个很长的列表,点某一项前进到详细页面,再返回的话,默认情况是会还原列表页面的初始状态,也就是用户会发现列表又滚到最上面了,要重新滚,可能会被打1星,所以要稍微撸一下:

在前一个页面的构造函数里加一个NavigationCacheMode进去

public MainPage()
{
    InitializeComponent();
    NavigationCacheMode = NavigationCacheMode.Enabled;
}
这样后退的时候就能保持前一个页面的状态了。

1. Adaptive UI

1. 为ListView设置VisualStateGroup,使得窗口宽度小于500时,image不显示
 <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="VisualStateGroup">
                <VisualState x:Name="VisualStateMin0">
                    <VisualState.Setters>
                        <Setter Target="InlineToDoItemViewGrid.(UIElement.Visibility)" Value="Collapsed"/>
                        <Setter Target="ToDoListView.(Grid.ColumnSpan)" Value="2"/>
                    </VisualState.Setters>
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="1"/>
                    </VisualState.StateTriggers>
                </VisualState>
                <VisualState x:Name="VisualStateMin800">
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="800"/>
                    </VisualState.StateTriggers>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

用VisualStateManager.VisualStateGroups组织一个管理配置(?),下设多个VisualState表示不同的UI方案;

  • VisualState.StateTriggers下组织触发方案的具体条件;

    • AdaptiveTrigger用事件具体设定触发方案的具体条件;
  • VisualState.Setter组织方案中对元素的设置;

    • Setter的Target通过x:Name的值指定想要设置的控件的property,Value设置值。

好像无法控制List里的Image属性。。。
解决:DataTemplate嵌套。
Done.

2.在宽屏显示两列的情况下,点击ADD Button不会跳转到EditToDos页面
<Setter Target="AddAppBarButton.Click" Value=""/>

2.Data Binding

将ListView的Item设置Data Binding(包括日期)

遇到了蜜汁bug。

xmlns:md="using:Todos.Models"
...
<DataTemplate x:DataType="md:TodoItem">

检查过n遍没打错字,死都找不到TodoItem这个类。
怎么都搞不定,最后重新建了个项目又copy了一次demo的东西就好了。
我:?????

.实现Update,Delete函数

宽屏状态下,修改子页信息,update后可保存,delete后子页为空
窄屏沿用week2逻辑

DateTime,Date, DateTimeOffset这三个类:
DateTime和Date之间可以直接赋值。
DateTimeOffset.DateTime 这个属性就可以转换,貌似会丢失些信息,影响不大。
经常会碰到检查null的问题。

Update不知为何不能更新list中的信息,实际上已经修改了能在子页显示,但是list不会自动刷新……。
一个不错的ref:http://www.cnblogs.com/durow/p/4893195.html

在View中就需要这样绑定:
这里写图片描述
需要注意的是x:Bind 默认的绑定方式是OneTime ,即只绑定一次,在使用时记得根据需求改成OneWay或TwoWay。
这里写图片描述
此外还需要说明的是,x:Bind的绑定是强类型的,如果遇到绑定源为Object(例如绑定ListView的SelectedItem)需要进行强制类型转换。如下图所示,其中local为TestData所在命名空间。

改成OneWay,还是不行。

 <ListView x:Name="ToDoListView" IsItemClickEnabled="True" 
                      ItemClick="TodoItem_ItemClicked"
                      ItemsSource="{x:Bind ViewModel.AllItems, Mode=OneWay}" Grid.Column="0">

3/12: 用一个邪门技巧,在点完CreateButton之后调用navigate方法刷新,就可以刷新ListView了,但这似乎不符合要求啊….

 Frame.Navigate(typeof(MainPage), ViewModel); // 点击完后刷新页面以载入新的ListView

绑定弄好了就没问题了。Done!

宽屏状态下 点击todo list中的一项会在右边界面自动进入Edit界面并补全信息。

绑定的时候很麻烦,数据类型不同要转换,然后涉及到x:Bind里Converter的使用。
先看了个博客 ref:http://www.cnblogs.com/webabcd/p/5648722.html

看完还是不懂,最后找到了微软官方的XAML Binding示例,终于懂了/(ㄒoㄒ)/~~
Ref: https://code.msdn.microsoft.com/windowsapps/Data-Binding-7b1d67b5/
果然还是具体场景的例子最有教学意义了。
Sceneario2converter必须实现接口IValueConverter。

C#:


namespace DataBinding
{
    // This value converter is used in Scenario 2. For more information on Value Converters, see http://go.microsoft.com/fwlink/?LinkId=254639#data_conversions

    public class S2Formatter : IValueConverter
    {
        //Convert the slider value into Grades
        public object Convert(object value, System.Type type, object parameter, string language)
        {
            // LOGIC
            return _grade;
        }

        public object ConvertBack(object value, System.Type type, object parameter, string language)
        {
            throw new NotImplementedException(); //doing one-way binding so this is not required.
        }
    }
}

XAML:


      <StackPanel>
        <Border BorderBrush="LightBlue" BorderThickness="4" CornerRadius="20" Margin="5">
          <StackPanel Margin="5">
            <!-- Add converter as a resource to reference it from a Binding. -->
            <StackPanel.Resources>
            //  在layout控件里用*.Resources管理资源
                 <local:S2Formatter x:Key="GradeConverter"/>
            </StackPanel.Resources>
            ...
            <TextBox x:Name="tbValueConverterDataBound" Text="{Binding     ElementName=sliderValueConverter, Path=Value, Mode=OneWay, 
             Converter={StaticResource GradeConverter}}" Margin="5" Width="150"/>
             ...

好了,搞完两个转换器,发现VS一直提示我找不到 NullToBoolConverter(其实是bool到nullable的转换器)。
多次改变.Resources标签,无果。
有可能是函数本身编写不对,返回类型错误了。然后用别的方法又写了一次,用了TypeConverter不知道为什么没法用,然后又换了种写法/(ㄒoㄒ)/这次是跟的msdn上的例子。
https://msdn.microsoft.com/zh-cn/library/bb342869(v=vs.110).aspx#示例

public object Convert(object value, System.Type type, object parameter, string language)
        {
            XAttribute bl = new XAttribute("BoolValue1", value);
            bool? result = (bool?)bl;
            return result;
        }
        // 其实一点都看不懂

然后还是报错

cannot find the resourse with the given key

又开始漫长的搜索……
有人是因为文件链接不对(其实也没看出来哪儿不对)
http://stackoverflow.com/questions/33730153/cannot-find-a-resource-with-the-name-key-navigationpanebutton

想试着用Resource Dictionary添加,然后按一个.NET Framework的语法写了半天都报错,还想着我TM到底错哪儿了……应该看这个才对
https://docs.microsoft.com/en-us/windows/uwp/controls-and-patterns/resourcedictionary-and-xaml-resource-references
切记搜什么都要带上uwp前缀才不会再次出现惨剧。。

用了正确的添加方法终于成功了T T

    <Page.Resources>
        <db:NullToBoolConverter x:Key="NullToBoolConverter"/>
    </Page.Resources>

回头这么一看真是做了好多无用功啊唉……
结论就是用Page.Resource可以保证正确绑定转换器,用次级控件(就是官方给的例子里的做法)就·可能失败了。所以我是被微软坑了么。。。

下面开始做补全。
今天早上刚开始做的时候就可以补全不需要转换的title和description了,不知道为什么现在又不行了。。。
不知道要不要用x:Bind做,我已经煞费苦心写了

Date="{x:Bind ViewModel.SelectedItem.date, Converter={StaticResource DateTimeToDateTimeOffsetConverter}}"/>

先用后台绑着吧..

Done.

5. AddAppBarButton

窄屏:没有选中item:跳转到NewPage;选中item:NewPage为Update
宽屏:点击就清空子页,并且createButton显示为“Create”,执行创建新item的逻辑,标题为“New Todo”;区别:修改已有item时标题为“Edit Todo”

窄屏时不会跳转到新页面了–用Window.Current.Bounds.Width控制。
主要修改了NewPage的OnNavigatedTo和CreateButton_Clicked函数。
Done.

6.DeleteAppBarButton
  • 删除完后子页标题更改
  • 进入单屏编辑时点击删除要返回主页

Done.

ListView
  • 飞出菜单绑定相应函数

涉及设置MenuFlyItem的Command属性问题。
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/e12f1f8e-429f-4dfb-9d74-b38c5d1b5643/menuflyout-menuflyoutitem-command-databinding-with-sender-as-parameter?forum=wpdevelop
这个Command要Binding一个实现了ICommand的接口的类。传参用CommandParameter。如何实现:

xaml那块不确定怎么正确调用DeleteCommand,先试下。代码都铺好了,运行,点击delete毫无反应。

StOv:Send current item as command parameter in data template

StOv: XAML MenuFlyoutItem Command Binding in ListView

尝试了这两个的办法都没有用。(而且第二个问题跟我的情况几乎一模一样了)

<MenuFlyoutItem Text="Delete" Command="{Binding DataContext.DeleteCommand, ElementName=ToDoListView}" CommandParameter="{x:Bind id}" />

Command应该是没有设置错的,改变上下文为ToDoListView;
那就只能是CommandPatameter出错了。
嗯,反正我还没看出来。。。

3/14 嗯,依然没解决。TA说用Click就可以了。
有个关键问题是要使每个飞出菜单点击删除时绑定到它所在的object上,这个涉及click事件传递的参数到底怎么使用……
先分析一下,应该,MenuFlyoutitem的sender就是它自己,然后我现在要绑定的是它爸爸……
试下这么搜索:

Google: menuflyoutitem click binding parent

我的妈,居然还搜索到了!跟我猜的一样是用datacontext。

menuflyoutitem-get-parent
但是这里就看不懂了

Then you can get the ListViewItem from that DataContext.

ListViewItem item = this.NameOfYourList.ContainerFromItem(datacontext) as ListViewItem;

再认真看回复:

@blawford The datacontext is the item itself (not the ListViewItem but the exact context item). If you’re binding ListView.ItemsSource to ObservableCollection, just removing this datacontext from the ListView should immediately reflect in the ListView! – igrali Mar 8 ‘15 at 22:03

datacontext已经是item本身了,直接用就行。好,把我的代码改成

            MenuFlyoutItem se = sender as MenuFlyoutItem;
            var dc = se.DataContext as TodoItem;
            ViewModel.RemoveTodoItem(dc.id);

成功啦!
Done.

  • 未完成的项目没有删除线

将TodoItem.Completed绑定到CheckBox.check上。
Q:Boolean casting to System.Visibility
A: https://pmdevweb.wordpress.com/2016/05/24/uwp-binding-boolean-to-visibility/

又没绑定上,看起来像是双向绑定失败了。。后台数据没办法更新界面╮(╯_╰)╭

3/12 将初始item的completed设置为true,是可以勾选+显示删除线的;但是Adding Todo的构造item函数将默认completed设置为false还是显示了删除线。。
先确认,completed—>isChecked是对的?可以通过改变构造函数来测试。结果是对的。listitem的显示行为对于初始item是没问题的。
反向测试—–isChecked—>completed,也就是nullable bool—->bool:
https://msdn.microsoft.com/en-us/library/bb384091.aspx

直接问TA,才发现思路错了。绑定不上是因为我的Model没有实现INotifyPropertyChanged接口。虽然ObservalbleCollection有实现,但它只能检测到它自己的变化,对于每个原子元素内部它检测不了

TA我错了(。﹏。*)
没分析好原理,一直卡着,郁闷,看来还是同志仍需努力啊( ̄﹏ ̄;)可能要多用笔表达一下逻辑什么的。。。

Ref:
Windows_UI_Xaml_Data_INotifyPropertyChanged_PropertyChanged

Done!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  • 最窄屏时不显示图片

最窄屏时依然显示图片—确认是否触发了最窄屏方案—确认已触发,就是图片不消失。
貌似是因为DataTemplate里Adaptive UI会失效。
http://stackoverflow.com/questions/32088500/adaptivetrigger-and-datatemplate
解决办法:用<UserControl>标签在DateTemplate里做一层封装,里面就可以实现VisualState了!完美解决(鼓掌

Try wrapping your DataTemplate inside a UserControl like this -

<DataTemplate>
    <UserControl>
        <Grid>
            <VisualStateManager.VisualStateGroups>
            ...
        </Grid>
    </UserControl>
</DataTemplate>

msdn上对UserControl的说明:

UserControl Class
Provides the base class for defining a new control that encapsulates related existing controls and provides its own logic.

Done.

子页
  • MainPage启动时保证输入正常

BUG:从单屏删除后,跳回MainPage直接在右边子页“Add New Todo”输入会报错。打开程序不做任何操作直接输入也会挂……
–原因是子页绑定的SelectedItem没创建。在ViewModel的构造里添加一个TodoItem的默认构造,启动填写不报错了,单屏删除回来还是报错。
–OnNavigatedTo也添加这个“补丁”即可。

Done.


refs

{x:Bind} 标记扩展
https://docs.microsoft.com/zh-cn/windows/uwp/xaml-platform/x-bind-markup-extension

资源字典的使用
http://www.cnblogs.com/tianyou/archive/2012/12/07/2806835.html

创建:
    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    // 用x:Key定义资源名
    <LinearGradientBrush x:Key="FadeBrush">

 ...

        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Test.xaml"/>
            </ResourceDictionary.MergedDictionaries>

        ResourceDictionary.MergedDictionaries属性是一个ResourceDictionary对象的集合,可以使用这个集合提供自己需要使用的资源的集合。也就是说如果需要某个资源,只需要将与该资源相关的xaml文件。添加到这个属性中即可。如上面添加test.xaml一样。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值