据我所知,Command模式的目标是帮助将UI交互与应用程序逻辑分开.使用正确实现的命令,单击"打印"菜单项可能会产生一系列交互,如下所示:
(button) ---click executes command----> (command) ---calls Print() in app logic ---> (logic)
Run Code Online (Sandbox Code Playgroud)
这鼓励您将UI与应用程序逻辑分开.
我一直在研究WPF命令,在大多数情况下,我看到他们是如何实现这种模式的.但是,我觉得在某种程度上它们使命令模式变得复杂,并设法以不鼓励将UI与应用程序逻辑分离的方式实现它.
例如,考虑这个简单的WPF窗口,它有一个按钮将文本粘贴到文本框中:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Paste"
Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
<StackPanel>
<TextBox x:Name="txtData" />
<Button Command="Paste" Content="Paste" />
</StackPanel>
</Window>
Run Code Online (Sandbox Code Playgroud)
这是代码隐藏:
namespace WpfApplication1
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
ApplicationCommands.Paste.Execute(null, txtData);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我从命令中获得了什么?在我看来,我可以轻松地将命令绑定事件处理程序中的代码放入按钮的Click事件中.当然,现在我可以将多个UI元素与粘贴命令相关联,我只需要使用一个事件处理程序,但是如果我想粘贴到几个不同的文本框呢?我必须使事件处理程序逻辑更复杂或编写更多的事件处理程序.所以现在,我觉得我有这个:
(button) ---executes Routed Command---> (Window) ---executes command …Run Code Online (Sandbox Code Playgroud) 我正在为一个不支持Unicode字符串但仍支持多字节ANSI字符串的库的PInvoke包装器工作.在调查关于库的FxCop报告时,我注意到使用的字符串编组有一些有趣的副作用.PInvoke方法使用"最佳拟合"映射来创建单字节ANSI字符串.为了说明,这是一个方法的样子:
[DllImport("thedll.dll", CharSet=CharSet.Ansi)]
public static extern int CreateNewResource(string resourceName);
Run Code Online (Sandbox Code Playgroud)
使用包含非ASCII字符的字符串调用此函数的结果是Windows找到"关闭"字符,通常这看起来最终是"???".如果我们假装'a'是非ASCII字符,那么将"cat"作为参数传递将创建名为"c?t"的资源.
如果我遵循FxCop规则中的指导原则,我最终会得到这样的结果:
[DllImport("thedll.dll", CharSet=CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern int CreateNewResource([MarshalAs(UnmanagedType.LPStr)] string resourceName);
Run Code Online (Sandbox Code Playgroud)
这引入了行为的变化; 现在当一个字符无法映射时抛出一个异常.这让我很担心,因为这是一个突破性的变化,所以我想尝试将字符串编组为多字节ANSI,但我看不到这样做的方法. UnmanagedType.LPStr被指定为单字节ANSI字符串,LPTStr will be Unicode or ANSI depending on the system, and LPWStr is not what the library expects.
How would I tell PInvoke to marshal the string as a multibyte string? I see there's a WideCharToMultiByte()
UnmanagedType.LPStrLPTStr will be Unicode or ANSI depending on the system, and LPWStr is …
这似乎是一个普遍的问题.我已经回顾了5或6个其他SO问题,似乎没有一个问题完全符合这个案例,或者有一个适合我的解决方案.在这一点上,我甚至不确定我是否关心"如何解决它"作为"为什么会发生这种情况".善待,HTML不是我的专长.
我有这个HTML/CSS:
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body {
background: #336699;
}
.postContainer {
margin-left: 40px;
background: white;
width: 555px; /* 480px + 75 for bg */
}
.postTop {
background: red;
height: 75px;
padding-left: 80px;
}
.postMiddle {
background: yellow;
padding-left: 80px;
}
.postBottom {
background: red;
height: 75px;
padding-left: 80px;
}
</style>
</head>
<body>
<div class="postColumn">
<div class="postContainer">
<div class="postTop">
<p>asdf</p>
</div>
<div class="postMiddle">
<p>asdf</p>
</div>
<div class="postBottom">
<p>asdf</p>
</div>
</div>
</div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
我已经剥掉了很多东西; 我们的目标是建立一个博客文章,其中包含一个顶部,一个拉伸的中间部分和一个左下部的图像.因此,顶部区域将有一小段文本,中间区域是任意数量,底部区域是一行的文本值.但由于div之间存在一些空间,因此图像不会对齐.
我检查了Firebug和Chrome的开发工具的边距; …
我在布局方面遇到了很多其他需要大量额外InvalidateLayout()调用的问题,所以我开始质疑我是否了解RelativeLayout是如何工作的.
以下是需要右对齐标签的UI的一个非常简单的示例:
public class MainPage : ContentPage {
public MainPage() {
var layout = new RelativeLayout();
var label = new Label() {
Text = "I want to be right-aligned."
};
layout.Children.Add(label,
Constraint.RelativeToParent((rl) => rl.Width - label.Width),
Constraint.Constant(10));
var button = new Button() {
Text = "Invalidate"
};
button.Clicked += (object sender, EventArgs e) => layout.ForceLayout();
layout.Children.Add(button,
Constraint.Constant(10),
Constraint.Constant(10));
Content = layout;
}
}
Run Code Online (Sandbox Code Playgroud)
我希望这可以从正确对齐的标签开始,但是在强制执行另一个布局传递之前,它不会正确对齐标签.通过在我的自定义控件中重写OnSizeRequest()等方法,我确定这是因为在调用RelativeLayout的约束lambdas之后才会调用OnSizeRequest().因此,当布局页面时,标签的宽度为-1.稍后调用ForceLayout()时,Label有机会执行其布局逻辑并正确设置Width属性,因此它可以正确布局.
在更大的背景下,我试图制作一个按钮,当点击时,淡出并且标签滑动到原位.它将在我的布局的右下角对齐,但我发现修改Opacity或IsVisible只会不一致地更新布局.唯一一致的行为是RelativeLayout真的喜欢在它有机会调整自身之前询问控件的大小.
我是否解释了如何使用RelativeLayout错误,或者这是错误的逻辑?
我试图在他们创建的疯狂情况下向某人展示接口的用途.它们在列表中有几个不相关的对象,需要对每个对象中的两个字符串属性执行操作.我指出,如果他们将属性定义为接口的一部分,他们可以使用接口对象作为作用于它的方法参数的类型; 例如:
void PrintProperties(IEnumerable<ISpecialProperties> list)
{
foreach (var item in list)
{
Console.WriteLine("{0} {1}", item.Prop1, item.Prop2);
}
}Run Code Online (Sandbox Code Playgroud)
这似乎一切都很好,但是需要处理的列表不是(也不应该)使用接口作为类型参数声明.但是,您似乎无法转换为其他类型参数.例如,这失败了,我无法理解为什么:
using System;
using System.Collections.Generic;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
List<Test> myList = new List<Test>();
for (int i = 0; i < 5; i++)
{
myList.Add(new Test());
}
PrintList((IEnumerable<IDoSomething>)myList);
}
static void PrintList(IEnumerable<IDoSomething> list)
{
foreach (IDoSomething item in list)
{
item.DoSomething();
}
}
}
interface IDoSomething
{
void DoSomething();
}
public class Test : IDoSomething …Run Code Online (Sandbox Code Playgroud) 我正在通过重构他们所从事的大型项目来教授更好的实践.该应用程序的当前功能之一是在Windows启动时启动应用程序的选项.目前,应用程序使用Run注册表项完成此操作:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
Run Code Online (Sandbox Code Playgroud)
我以前没有必要实现这个功能,所以我不确定这是否是在启动时运行应用程序的"最佳"方式.访问此注册表项是大多数用户将拥有的吗?
是否更好地将应用程序的快捷方式放在指示的文件夹中Environment.GetFolderPath(SpecialFolder.Startup)?似乎从.NET创建快捷方式是一种hacky,所以我不确定这是更好的.
编辑:
根据目前的回复,很明显我遗漏了一些重要的东西."以Windows启动"行为是可选的,是程序选项对话框的一部分.用户在使用应用程序时多次切换它是有效的(虽然很愚蠢).
我的.NET库必须将字符串封送到C库,该C库需要使用系统的默认ANSI代码页编码的文本.由于.NET支持Unicode,因此用户可以将字符串传递给未正确转换为ANSI的库.例如,在英语机器上,"デスクトップ"将变为"?????" 传递给C库时.
为了解决这个问题,我编写了一个方法,通过将原始字符串与使用ANSI代码页转换的字符串进行比较来检测何时发生这种情况.我想测试这个方法,但我确实需要一个保证不可编码的字符串.例如,我们在英语和日语机器(以及其他语言)上测试我们的代码.如果我编写测试以使用上面的日语字符串,当日语系统正确编码字符串时,测试将失败.我可以编写测试来检查当前系统的编码,但每次添加/删除新语言时我都会遇到维护噩梦.
是否存在不使用任何 ANSI代码页编码的unicode字符?如果失败了,是否可以使用来自足够不同代码页的字符构造字符串以保证失败?我的第一次尝试是使用汉字,因为我们没有覆盖中文,但显然日语可以转换我尝试过的汉字.
编辑我将接受现在提出格鲁吉亚字符串的答案,但实际上是期待一个来自不同语言的一些字符的结果.我不知道我们是否打算支持格鲁吉亚人,所以现在似乎还可以.现在我必须在每种语言上测试它.喜悦!
任务API感觉有点像失败的坑,给每一个可能的事情,我可以用它做怎样带有更多DO NOT比DO.但是我试图更多地使用它,我对整个问题感到困惑async void.
我的问题发生在我的应用程序永远使用本地数据文件的地方,因为它使用了快速同步调用.现在一些远程源是一个选项,它们有足够的延迟我将它全部切换为异步.
所以我有一个方法可能看起来像这样:
void InitializeData() {
SomeProperty = _dataSource.Load(...);
}
Run Code Online (Sandbox Code Playgroud)
我想为低摩擦做的天真的事情是:
Task InitializeDataAsync() {
return Task.Run(() => {
SomeProperty = _dataSource.Load(...);
});
}
Run Code Online (Sandbox Code Playgroud)
但是有很多关于使用它有多可怕的文章async void,并且它们似乎在讨论返回任务时变得模糊.所以我最好的选择就是这样写:
Task<DataType> FetchDataAsync() {
return _dataSource.LoadAsync(...);
}
Run Code Online (Sandbox Code Playgroud)
...然后追捕所有来电者并让他们遵守?
我觉得人们所做的论证async void是不好的,因为async Task你使用时的不同行为和可怕的UnobservedTaskException await.在这种情况下,我不太可能使用await.或者,如果我使用await,它总是会有一个try/catch,因为我们已经对UnobservedTaskException产生了偏执.
所以:
async void" 和"不要使用"相同Task吗?await,它会缓解吗?await,总是用try/catch包装它可以缓解这个问题吗?