我是UWP的新手,正在使用模板10。 不过,我已经做了很多WPF。 我希望应用程序从打开或关闭汉堡菜单开始,具体取决于用户上次使用该应用程序时离开它的方式。 为此,我做了一个首选项,并将IsOpen绑定到我的设置视图模型中的属性。
但是,它不起作用。 启动应用程序时,视图模型中的属性始终从控件设置为 true。 我添加了一个按钮来更改视图模型属性(这将执行 raisepropertychanged),但它没有切换菜单。 但是,使用鼠标从 UI 切换菜单将调用我的视图模型中的 setter。
这是我所做的:
-
我使用汉堡包模板创建了一个新项目。
-
我在设置服务中添加了一个新属性。 它镜像设置服务中其他属性的格式
public bool HamburgerIsOpen { get { return _helper.Read<bool>(nameof(HamburgerIsOpen), true); } set { _helper.Write(nameof(HamburgerIsOpen), value); } }
-
我在 SettingsPartViewModel 中添加了一个新属性。 它镜像设置部件视图模型中其他属性的格式
public bool HamburgerIsOpen { get { return _settings.HamburgerIsOpen; } set { _settings.HamburgerIsOpen = value; base.RaisePropertyChanged(); } }
-
我更新了 Shell.xaml,添加了数据上下文和绑定
<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。
任何想法我该怎么做?
谢谢。
将汉堡包设置为打开的原因是因为它IsOpen
属性的回退值为 True。可能{Binding}
失败了,因为它无法访问它或只是找不到它。因为您使用的是UWP
和Template10
。我建议:
- 使用
{x:Bind}
而不是{Binding}
,因为这样你就可以知道编译器是否可以找到提供的绑定引用。
在 Shell.xaml
viewModel
中创建 a 属性(假设您使用的是Hamburger Template
)或者如果没有? 然后在使用该HamburgerControl
的View
的viewModel
创建一个属性。- 现在,在该
property
中,您从Get
中的SettingsPageViewModel.SettingsPartViewModel.HamburgerIsOpen
获取数据,并将新值更新为set
中的相同值。这样,您就可以在使用汉堡包的视图的viewModel
中拥有所需的数据。 - 现在
x:Bind
IsOpen
属性到Mode=TwoWay
中的属性。现在,您将拥有一个功能齐全的汉堡菜单,其中包含恢复状态。注意:如果要x:Bind
属性,请确保将ViewModel.
前缀添加到绑定中,并将<DataContext>
命名为ViewModel
。
抱歉,我不得不删除所有代码,也许是因为我会在这里放置代码,而旧的代码不再相关或可以从编辑中找到。
说到重点,我已经解决了这个问题,似乎有一些调用服务调用汉堡包控件并将值设置为false
视图尚未加载。我想出了一种相当厚颜无耻的方法来获得一个相当整洁的工作,有些人可能会说这并不理想,但这是一个修复。
守则:
在您的Shell.xmal
全局中创建一个bool
属性,例如:private bool loaded = false;
.这是一个属性,可以帮助我们知道视图是否已加载,因为对 setter 的所有调用都是在应用程序尚未加载的情况下进行的,似乎可以通过传递它并允许 getter 访问它。
现在在你的Shell.xaml
构造函数订阅外壳。加载事件,
例如:this.Loaded += Shell_Loaded; //in the shell.xmal.cs constructor
和Shell_Loaded
事件:
private void Shell_Loaded(object sender, RoutedEventArgs e)=>
loaded = true;
请注意,方法语法是 c# 6.0 中用于较低版本的语法,请使用繁体{}
。
同样在shell.xaml.cs
中添加bool
属性以处理汉堡菜单的打开/关闭
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;
}
}
请注意:我正在创建视图模型的实例,以便通过设置视图模型更改所有设置。如果某些设置开始变得有趣,我们会知道在哪里可以找到它们。
您的Shell.xaml
在汉堡控件中,将其链接到属性背后的代码,
<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
并将其x:Bind
到 ViewModel。
<ToggleSwitch x:Name="OpenHamWhenStart"
Header="Default Hamburger Open or Close"
IsOn="{Binding IsHamOpen, Mode=TwoWay}"
OffContent="Hamburger Menu is Closed"
OnContent="Hamburger Menu is Open"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.Below="BusyTextTextBox" />
你有它。如果有任何问题,请告诉我。您可以在评论部分与我联系
好的 - 这就是我最终做的事情。 对我来说,这似乎比跟踪加载等更简单。 这对我来说仍然像是模板 10 中的一个错误,但这可以解决它。 长话短说,我不在 XAML 中进行绑定,而是在页面加载后进行绑定
Shell.xaml -> 为页面上的 Loaded 创建一个事件处理程序,在 IsOpen 上没有绑定并设置数据上下文。
Loaded="Shell_OnLoaded"
...
<Page.DataContext>
<viewModels:SettingsPageViewModel x:Name="ViewModel" />
</Page.DataContext>
<Controls:HamburgerMenu x:Name="MyHamburgerMenu">
Shell.xaml.cs -> 这里是 IsLoad 的事件处理程序。 它在加载页面后设置绑定。 这将阻止汉堡包控件在加载时将设置设置为 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);
}
设置页面视图模型.cs ->定义属性
public bool HamburgerIsOpen
{
get { return _settings.HamburgerIsOpen; }
set { _settings.HamburgerIsOpen = value; base.RaisePropertyChanged(); }
}
设置服务.cs ->定义保存机制。 无需像设置服务中的其他属性那样调用视图...
public bool HamburgerIsOpen
{
get { return _helper.Read<bool>(nameof(HamburgerIsOpen), true); }
set
{
_helper.Write(nameof(HamburgerIsOpen), value);
}
}