WPF Image异步加载控件

ImageLoadingControl使用说明

控件提供Source属性,可Binding图片Url或Path

1
2
3
<ImageLoadingControl:ImageLoadingControl HorizontalAlignment="Left" Height="200" Margin="30,68,0,0" VerticalAlignment="Top" Width="200"  Source="{Binding ImageUrl1}"/>
<ImageLoadingControl:ImageLoadingControl HorizontalAlignment="Left" Height="200" Margin="303,68,0,0" VerticalAlignment="Top" Width="200" Source="{Binding ImageUrl2}"/>
<ImageLoadingControl:ImageLoadingControl HorizontalAlignment="Left" Height="200" Margin="556,68,0,0" VerticalAlignment="Top" Width="200" Source="{Binding ImageUrl3}"/>
1
2
3
4
5
6
private void button_Click(object sender, RoutedEventArgs e)
{
ImageUrl1 = @"https://pixabay.com/static/uploads/photo/2016/02/09/13/45/rock-carvings-1189288_960_720.jpg";
ImageUrl2 = @"https://pixabay.com/static/uploads/photo/2016/02/14/14/32/construction-1199586_960_720.jpg";
ImageUrl3 = @"c:\test.jpg";
}

下图分别显示了控件加载中,加载完成,加载失败三种状态:

阅读更多

WPF使用BitmapImage内存释放问题

在WPF中进行图片的相关操作是一件比较麻烦的事,并不是说它复杂,而是不注意的话很容易引起内存暴涨甚至溢出。关于BitmapImage使用的相关说明如下:

一、 创建方式

使用Uri设置BitmapImage会自动形成缓存,不关闭整个模块的话GC不会回收。 故如果在单个模块多次显示图片,不要使用这种方式:

var bitmap = new BitmapImage(new Uri(@"c:\test.bmp"));

建议通过流的方式加载图片:

阅读更多

WPF异步加载BitmapImage

在WPF中异步获取HTTP图片并赋值给Image控件,遇到诸多问题,如多线程队列,资源不释放等,最终琢磨出下面的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (s, e) =>
{
Uri uri = e.Argument as Uri;

using (WebClient webClient = new WebClient())
{
webClient.Proxy = null;
webClient.CachePolicy = new RequestCachePolicy(RequestCacheLevel.Default);
try
{
byte[] imageBytes = null;

imageBytes = webClient.DownloadData(uri);

if (imageBytes == null)
{
e.Result = null;
return;
}
MemoryStream imageStream = new MemoryStream(imageBytes);
BitmapImage image = new BitmapImage();

image.BeginInit();
image.StreamSource = imageStream;
image.CacheOption = BitmapCacheOption.OnLoad;
image.EndInit();

image.Freeze();
imageStream.Close();

e.Result = image;
}
catch (WebException ex)
{
e.Result = ex;
}
}
};

worker.RunWorkerCompleted += (s, e) =>
{
BitmapImage bitmapImage = e.Result as BitmapImage;
if (bitmapImage != null)
{
myImage.Source = bitmapImage;
}
worker.Dispose();
};

worker.RunWorkerAsync(imageUri);

EntityFramework5.0与WCF使用遇到的问题

在使用EntityFramework5.0,并将其作为WCF放在服务端的时候遇到了如下问题:

1. EF在客户端与服务端之间传输问题

由于将EF放在服务端,所以类必须具有DataContract属性。

服务契约定义了远程访问对象和可供调用的方法,数据契约则是服务端和客户端之间要传送的自定义数据类型。

只有声明为DataContract的类型的对象可以被传送,且只有成员属性会被传递,成员方法不会被传递。WCF对声明为DataContract的类型提供更加细节的控制,可以把一个成员排除在序列化范围以外,也就是说,客户端程序不会获得被排除在外的成员的任何信息,包括定义和数据。默认情况下,所有的成员属性都被排除在外,因此需要把每一个要传送的成员声明为DataMember,如下所示。

阅读更多

资源键Key

1. 什么是资源键

资源键x:Key用作创建和引用资源的唯一标识,作用类似于名称,常出现在ResourceDictionary中且要求必须为 ResourceDictionary 内的每项定义一个键。

例:

1
2
3
4
5
6
<ResourceDictionary>
<LinearGradientBrush x:Key="fadeBrush">
<GradientStop Color="Red" Offset="0"/>
<GradientStop Color="Gray" Offset="1"/>
</LinearGradientBrush>
</ResourceDictionary>

但带有DataType的数据模板DataTemplate和带有TargetTypeStyle属于特殊情况,他们本身带有隐式键。

阅读更多

如何在WPF中停止线程

1. Abort的非及时性

使用多线程经常会遇到一个问题,如何停止这个Thread?在WPF中提供了Abort方法,但MSDN却告诉我们:

线程不一定会立即中止,或者根本不中止。 如果线程在作为中止过程的一部分被调用的 finally 块中做非常大量的计算,从而无限期延迟中止操作,则会发生这种情况。

先看下面一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public partial class MainWindow : Window
{
Thread thread;
public MainWindow()
{
InitializeComponent();
Test t = new Test();
thread = new Thread(new ThreadStart(t.Run));
thread.Start();

}

private void Button_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("abort");
thread.Abort();
}
}

public class Test
{
public void Run()
{
while (true)
{
Console.WriteLine("Running...");
}
}
}
阅读更多

在ControlTemplate中使用VisualTreeHelper和LogicalTreeHelper

在TabControl中给TabItem定义如下的Template:

1
2
3
4
5
6
7
8
9
10
11
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid x:Name="templateRoot" SnapsToDevicePixels="true">
<Border x:Name="mainBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,1,1,0" Background="{TemplateBinding Background}" Margin="0">
<Border x:Name="innerBorder" BorderBrush="{StaticResource TabItem.Selected.Border}" BorderThickness="1,1,1,0" Background="{StaticResource TabItem.Selected.Background}" Margin="-1" Opacity="0"/>
</Border>
<DockPanel Margin="2,0">
<Button Click="Button_Click" DockPanel.Dock="Right" Content="X" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="Blue"/>
<ContentPresenter x:Name="contentPresenter" ContentSource="Header" Focusable="False" HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
</DockPanel>
</Grid>
</ControlTemplate>

实现的效果是给每一个TabItem添加关闭按钮:

现在需要实现关闭按钮的功能,那么则需要在后台Button_Click事件中通过sender找到类型为TabItem的parent。

阅读更多

管理员权限打开VisualStudio无法访问网络磁盘的解决办法

【问题产生】

问题最初是在administrator权限下,visual studio 打开网络磁盘下的文件报错。经过几次调试,最终发现是问题是在管理员权限下,vs无法访问网络磁盘。

Console.Write( System.IO.File.Exists(path));

该结果返回False。为了确认是由于权限问题引起,使用非管理员权限打开vs,运行上面的程序,结果返回True。

至此问题确立:win7/win8下,使用管理员权限打开VisualStudio,无法访问网络磁盘。

阅读更多

WPF中ListView使用GridViewColumn居中对齐的方法

在WPF中使用ListView经常会用到GridView作为视图,但是却碰到GridViewColumn不能居中对齐的问题,首先想到不使用GridViewColumn的DisplayMemberBinding属性,直接设置DataTemplate,于是尝试修改代码为:

1
2
3
4
5
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock TextAlignment="Center" Text="{Binding XX}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>

结果还是不行,因为TextBlock的Width是根据Text内容自动调整,没有填充整个单元格,所以需要调整填充样式。方法有两种:

【方案一】

将DataTemplate元素的MinWidth和单元格的ActualWidth绑定,这样就能让DataTemplate元素始终填满单元格:

阅读更多

WPF使用MediaElement方法介绍

在WPF或Silverlight中使用MediaElement控件可以方便的制作一个视频音频播放器。

首先制作一个UserControl:

代码如下:

1
2
3
4
5
6
7
8
9
10
11
<DockPanel Height="387">
<StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom">
<Button Height="23" HorizontalAlignment="Left" Margin="16,0,0,10" x:Name="btnPlay" VerticalAlignment="Bottom" Width="75" Click="btnPlay_Click">播放</Button>
<Button Height="23" HorizontalAlignment="Left" Margin="16,0,0,10" x:Name="btnPause" VerticalAlignment="Bottom" Width="75" Click="btnPause_Click">暂停</Button>
<Label Content="音量:"/>
<Slider x:Name="sldVolumn" Value="{Binding Volume, ElementName=mePlayer, Mode=TwoWay, UpdateSourceTrigger=Default}" Maximum="1" LargeChange="0.1" SmallChange="0.01" Width="124" />
<Label Content="进度:"/>
<Slider x:Name="sldProgress" Minimum="0" Value="{Binding ElementName=mePlayer, Path=Position, Mode=TwoWay, Converter={StaticResource PrgConverter}}" LargeChange="10" Width="192" />
</StackPanel>
<MediaElement DockPanel.Dock="Top" Margin="16,23,12,39" x:Name="mePlayer" LoadedBehavior="Manual" MediaOpened="mePlayer_MediaOpened" />
</DockPanel>
阅读更多