码迷,mamicode.com
首页 > Windows程序 > 详细

WPF技巧 n问

时间:2016-07-11 18:41:40      阅读:481      评论:0      收藏:0      [点我收藏+]

标签:

问一:Popup控件Placement属性设置固定值后,在不同的电脑可能有不同行为的问题

Popup.Placement属性受SystemParameters.MenuDropAlignment(该值指示弹出菜单相对于相应菜单项是左对齐还是右对齐。)属性的影响,你可以这么设置:

if (SystemParameters.MenuDropAlignment)
{
	Popup.Placement = PlacementMode.Left;
}
else
{
	Popup.Placement = PlacementMode.Right;
}

问二:将ListBox的ItemsSource,Binding到List<String>为什么ListBox里面不是String列表而是ListBoxItem列表呢?

ItemsControl有两个虚方法:

protected override DependencyObject GetContainerForItemOverride()
{
      //return new CustomListItem();
}

protected override bool IsItemItsOwnContainerOverride(object item)
{
      //return item is CustomListItem;
}

顾名思义,这两个方法一个是判断有没有子项容器有没有被重写,一个是返回新的子项。你可以创建自己的ListBox,里面容纳自己的ListBoxItem,就像我上面那样(解掉两行注释)。

问三:如何以管理员身份启动应用程序?

在WPF项目添加应用程序清单文件app.manifest,找到如下所示的块:

<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <!-- UAC 清单选项
            如果要更改 Windows 用户帐户控制级别,请用以下节点之一替换 
            requestedExecutionLevel 节点。

        <requestedExecutionLevel  level="requireAdministratorasInvoker" uiAccess="false" />
        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />

            指定 requestedExecutionLevel 节点将会禁用文件和注册表虚拟化。
            如果要利用文件和注册表虚拟化实现向后 
            兼容性,则删除 requestedExecutionLevel 节点。
        -->
        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
</requestedPrivileges>

将<requestedExecutionLevel level="asInvoker" uiAccess="false" />改为<requestedExecutionLevel level="requireAdministratorasInvoker" uiAccess="false" /> 即可,这里还有其他选项,不作赘述。

问四:应用程序启动后如何检查是否以管理员身份运行的?

		/// <summary>
		/// 检查是否是管理员身份
		/// </summary>
		private void CheckAdministrator()
		{
			var wi = WindowsIdentity.GetCurrent();
			var wp = new WindowsPrincipal(wi);

			bool runAsAdmin = wp.IsInRole(WindowsBuiltInRole.Administrator);

			if (!runAsAdmin)
			{
				// It is not possible to launch a ClickOnce app as administrator directly,
				// so instead we launch the app as administrator in a new process.
				var processInfo = new ProcessStartInfo(Assembly.GetExecutingAssembly().CodeBase);

				// The following properties run the new process as administrator
				processInfo.UseShellExecute = true;
				processInfo.Verb = "runas";

				// Start the new process
				try
				{
					Process.Start(processInfo);
				}
				catch (Exception ex)
				{
					logger.Info(ex);
				}

				// Shut down the current process
				Environment.Exit(0);
			}
		}

在App构造函数或者App.OnStartup方法中调用。

问五:WPF无边框阴影窗口

看到这个问题你一定是如下设置吧:

<Window x:Class="WPFTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Width="525"
        Height="350"
        AllowsTransparency="True"
        Background="Transparent"
        WindowStyle="None">
    <Grid Margin="10" Background="White">
        <Grid.Effect>
            <DropShadowEffect BlurRadius="10" ShadowDepth="0" />
        </Grid.Effect>
    </Grid>
</Window>

技术分享

这样设置可以,但是窗体启动慢、性能低、不能拖动、不能拖改尺寸、不跟随系统窗口动画(最大化最小化时动态拉伸窗口)、没有窗体系统功能,另外你若这样设置窗口,窗口里面如果还有一个WebBrowser,那么这个WebBrowser不会显示。

WPF4.5新增了System.Windows.Shell命名空间,这个命名空间已经集成在了x:命名空间下,所以你现在可以这么创建窗口:

<Window x:Class="WPFTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Width="525"
        Height="350">
    <WindowChrome.WindowChrome>
        <WindowChrome CaptionHeight="30"
                      CornerRadius="0"
                      GlassFrameThickness="1"
                      NonClientFrameEdges="None"
                      ResizeBorderThickness="5"
                      UseAeroCaptionButtons="False" />
    </WindowChrome.WindowChrome>
    <Grid />
</Window>

技术分享

关于WindowChrome类,查阅MSDN在线文档:WindowChrome

问六:WPF路由命令的可用状态不能及时刷新到UI控件的问题

路由命令的CanExecute事件并不是不停的“投石问路”的。路由命令处于性能考虑在窗体是激活状态的时候才会不停地“投石问路”,但有时候也是会出现不触发的情况,这个时候你需要点击一下窗体其他地方,触发一下焦点切换,才会再次执行CanExecute事件。如何避免这个问题,而让WPF始终不停地“投石问路”呢?

static ControlCommands()
{
         DispatcherTimer dt = new DispatcherTimer
         {
                Interval = TimeSpan.FromMilliseconds(500)
         };
         dt.Tick += (sender, e) =>
         {
		//强制 System.Windows.Input.CommandManager 引发 System.Windows.Input.CommandManager.RequerySuggested事件
                CommandManager.InvalidateRequerySuggested();
         };
         dt.Start();
}

使用Tick里面的代码强制路由命令执行CanExecute事件。

问七:属性的更改通知、集合的更改通知

属性的更改通知要实现INotifyPropertyChanged接口,如:

public class MyClass : INotifyPropertyChanged
{
	public event PropertyChangedEventHandler PropertyChanged;

	private void RaisePropertyChanged(string propertyname)
	{
		PropertyChangedEventHandler handle = this.PropertyChanged;
		if (!string.IsNullOrEmpty(propertyname) && handle != null)
		{
			handle.Invoke(this, new PropertyChangedEventArgs(propertyname));
		}
	}


	public string Property1
	{
		get { return this.Property1; }
		set
		{
			this.Property1 = value;
			this.RaisePropertyChanged("Property1");
		}
	}
}

这样Property1属性就具备了更改通知的功能(在WPFUI中绑定此属性时)。

集合的更改通知要实现INotifyCollectionChanged接口,WPF本身只提供了一个这样的接口就是System.Collections.ObjectModel.ObservableCollection<T>类,ItemsControl的ItemsSource属性绑定到该类时,对该类进行的添加等操作会及时的更新到UI上,而不实现INotifyCollectionChanged接口的类则会报“绑定的集合与源集合不一致”异常。

 

 

第一次写博,欢迎大家批评指正。

持续更新中…

WPF技巧 n问

标签:

原文地址:http://www.cnblogs.com/Mr--Zhang/p/5661121.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!