我是UWP的新手并使用模板10.虽然我已经做了很多WPF。我希望应用程序可以根据用户上次使用应用程序时的方式打开或关闭汉堡包菜单。为此,我做了一个首选项,并将IsOpen绑定到我的设置视图模型中的属性。
然而,它不起作用。启动应用程序时,视图模型中的属性始终从控件设置为true。我添加了一个按钮来更改视图模型属性(这将执行raisepropertychanged)并且它没有切换菜单。但是,使用鼠标从UI切换菜单将在我的视图模型中调用setter。
这是我做的:
我使用汉堡模板创建了一个新项目。
我在SettingsService中添加了一个新属性。它反映了“设置服务”中其他属性的格式
public bool HamburgerIsOpen
{
get { return _helper.Read<bool>(nameof(HamburgerIsOpen), true); }
set
{
_helper.Write(nameof(HamburgerIsOpen), value);
}
}
我在SettingsPartViewModel中添加了一个新属性。它反映了SettingsPartViewModel
中其他属性的格式public bool HamburgerIsOpen
{
get { return _settings.HamburgerIsOpen; }
set { _settings.HamburgerIsOpen = value; base.RaisePropertyChanged(); }
}
我更新了Shell.xaml,添加了一个datacontext和绑定
<Page.DataContext>
<viewModels:SettingsPageViewModel x:Name="ViewModel" />
</Page.DataContext>
<Controls:HamburgerMenu x:Name="MyHamburgerMenu" IsOpen="{x:Bind ViewModel.SettingsPartViewModel.HamburgerIsOpen, Mode=TwoWay}">
控件肯定是在启动时将IsOpen设置为true,即使它首先返回false返回false。
我有什么想法可以做到这一点吗?
感谢。
答案 0 :(得分:1)
您的汉堡包设置为打开的原因是因为它的IsOpen
属性的回退值为True。可能{Binding}
失败了,因为它无法访问它,或者它无法找到它。因为您使用的是UWP
和Template10
。我建议:
{x:Bind}
代替{Binding}
,因为这样您就可以知道编译器是否可以找到您提供的绑定参考。 viewModel
的{{1}}中创建一个属性(假设您使用的是Shell.xaml
),或者如果没有?然后在Hamburger Template
的{{1}}中创建一个使用viewModel
的属性。 View
中,您可以从HamburgerControl
中的property
获取数据,并将新值更新为SettingsPageViewModel.SettingsPartViewModel.HamburgerIsOpen
中的相同内容。这样您就可以在使用汉堡包的视图的Get
中获得所需数据。set
viewModel
x:Bind
属性IsOpen
中的属性。现在,您将拥有一个功能齐全的汉堡菜单,其中包含恢复状态。 注意:如果您Mode=TwoWay
了您的媒体资源,请确保在绑定中添加x:Bind
前缀,并将ViewModel.
命名为<DataContext>
很抱歉,我必须删除所有代码,可能是因为我会在这里放置代码,而旧代码不再相关或可以从编辑中找到。
说到这一点,我已经解决了这个问题,似乎有一些调用服务调用Hamburger控件并在视图尚未加载时将值设置为ViewModel
。我想出了一个相当厚颜无耻的方法来得到一个非常整洁的工作,有些人可能会说它不理想,但它是一个修复。
在false
全局中创建Shell.xmal
属性,例如:bool
。这是一个帮助我们知道已加载视图的属性,因为所有对setter的调用都是在应用程序未加载的时候,通过传递它并允许getter访问它似乎没问题。
现在在private bool loaded = false;
构造函数中订阅shell.Loaded事件,
例如:Shell.xaml
和this.Loaded += Shell_Loaded; //in the shell.xmal.cs constructor
事件:
Shell_Loaded
注意方法语法是c#6.0中用于较低版本的语法,请使用传统的private void Shell_Loaded(object sender, RoutedEventArgs e)=>
loaded = true;
。
同样在{}
添加shell.xaml.cs
属性来处理汉堡菜单打开/关闭
bool
请注意:我正在创建ViewModel的实例,以便通过settingsViewModel更改所有设置。如果某些设置开始表现得很有趣,我们就会知道在哪里找到它们。
您的 Shell.xaml
在汉堡包控制中,将其链接到后面的代码
public bool IsHamOpen
{
get
{
return (new ViewModels.SettingsPageViewModel()).SettingsPartViewModel.IsHamOpen;
}
set
{
if (!value)
{
if (loaded)
{
(new ViewModels.SettingsPageViewModel()).SettingsPartViewModel.IsHamOpen = value;
}
else
(new ViewModels.SettingsPageViewModel()).SettingsPartViewModel.IsHamOpen = true;
}
else
(new ViewModels.SettingsPageViewModel()).SettingsPartViewModel.IsHamOpen = value;
}
}
在 SettingsPageViewModel:
中创建一个属性来处理对汉堡包菜单所做的更改。这种方式您还可以提供一个简单的切换开关,供用户默认选择打开或关闭他的汉堡包。
<Controls:HamburgerMenu x:Name="MyHamburgerMenu" IsOpen="{x:Bind IsHamOpen,Mode=TwoWay}">
在设置服务:
中添加属性以读取和写入设置并将其应用于汉堡包控件:
public bool IsHamOpen
{
get { return _settings.IsHamOpen; }
set
{
_settings.IsHamOpen = value;
base.RaisePropertyChanged();
//the below is to hide and show the hamburger button.
//If the it's open then hide button
//else show the button to open it.
//this is just as per your requiremnts.
//I just wanted to put it in
ShowHamburgerButton = !value;
}
}
最后设置视图
这是完全可选的。如果您希望用户能够设置他对汉堡包控件的偏好,请将整齐的 public bool IsHamOpen
{
get { return _helper.Read<bool>(nameof(IsHamOpen), false); }
set
{
_helper.Write(nameof(IsHamOpen), value);
Views.Shell.HamburgerMenu.IsOpen = value;
}
}
和toggleSwitch
提供给ViewModel。
x:Bind
你有它。如果有任何问题,请告诉我。你可以在评论栏目上与我联系
答案 1 :(得分:-1)
好的 - 这就是我最终要做的事情。对我来说似乎比跟踪加载等更简单。这在模板10中对我来说仍然感觉像是一个错误,但这将解决它。长话短说,我没有在XAML中进行绑定,我在页面加载后执行此操作
Shell.xaml - &gt;在页面上为Loaded创建一个事件处理程序,在IsOpen上没有绑定并设置数据上下文。
Loaded="Shell_OnLoaded"
...
<Page.DataContext>
<viewModels:SettingsPageViewModel x:Name="ViewModel" />
</Page.DataContext>
<Controls:HamburgerMenu x:Name="MyHamburgerMenu">
Shell.xaml.cs - &gt;这是IsLoaded的事件处理程序。它设置页面加载的绑定 AFTER 。这会阻止汉堡控制在加载时将设置设置为true。
private void Shell_OnLoaded(object sender, RoutedEventArgs e)
{
// now that the hamburger control is loaded, bind it for the future opening and closing
// if you bind it in XAML, the control always passes the value of true on load to the binding
// so the control always starts open
Binding myBinding = new Binding
{
Path = new PropertyPath("HamburgerIsOpen"),
Source = Services.SettingsServices.SettingsService.Instance,
Mode = BindingMode.TwoWay
};
MyHamburgerMenu.SetBinding(HamburgerMenu.IsOpenProperty, myBinding);
}
SettingsPageViewModel.cs - &gt;定义属性
public bool HamburgerIsOpen
{
get { return _settings.HamburgerIsOpen; }
set { _settings.HamburgerIsOpen = value; base.RaisePropertyChanged(); }
}
SettingsService.cs - &gt;定义保存机制。无需像SettingsService中的其他属性那样调用视图...
public bool HamburgerIsOpen
{
get { return _helper.Read<bool>(nameof(HamburgerIsOpen), true); }
set
{
_helper.Write(nameof(HamburgerIsOpen), value);
}
}