XAML 绑定 BitmapImage ViewModel 属性
我在从视图模型类更新列表框时遇到问题。我使用 Caliburn Micro 框架。我的场景如下:
我在列表框中绑定bindableCollection类型的属性:
来自视图模型的代码:
private BindableCollection<UserInfo> _friends;
public BindableCollection<UserInfo> Friends
{
get { return _friends; }
set
{
_friends= value;
NotifyOfPropertyChange(()=>Friends);
}
}
在视图模型中,我创建了一个假服务方法,该方法将新的新鲜数据作为列表返回,并使用此数据更新属性绑定在列表框上的好友。
我每 3 秒在调度程序计时器滴答事件中调用一次假服务方法。
private static UserInfo FakeUser()
{
var user = new UserInfo
{
Age = "16",
Emphasis = true,
IdUser = "11542",
IsBlocked = false,
IsFriend = true,
LocationInfo = new Location
{
CityName = "TN",
IdCity = 123456,
IdRegion = 1246,
RegionName = "TN",
},
StatusInfo = new Status
{
IdChat = 12,
IsLogged = true,
LastLogin = "153151",
IsChating = true,
RoomName = "Car",
},
ProjectStatusInfo = new ProjectStatus(),
IsIamFriend = true,
PlusInfo = new Plus(),
ProfilePhoto = new BitmapImage(new Uri("http://pokec.azet.sk/vanes90?i9=1f104a294997", UriKind.RelativeOrAbsolute))
};
return user;
}
private static IEnumerable<UserInfo> GetFakeFriends()
{
var list = new List<UserInfo>();
for (int i = 0; i < 20; i++)
{
list.Add(FakeUser());
}
return list;
}
private void DispatcherTimer_Tick(object sender, EventArgs eventArgs)
{
if (_isExecuting)
return;
_isExecuting = true;
new System.Threading.Tasks.Task(() =>
{
var freshFriends = GetFakeFriends();
Execute.OnUIThread((System.Action)(() =>
{
Friends.Clear();
foreach (var freshFriend in freshFriends)
{
Friends.Add(freshFriend);
}
}));
}).Start();
_isExecuting = false;
}
}
如果我不在列表框中应用任何样式,它效果很好。
视图:
<Grid>
<ListBox Name="Friends"
Grid.Row="2"
Margin="4,4,4,4">
</ListBox>
</Grid>
如果我应用某种样式,在列表框中从 UserInfo 绑定属性 ProfilePhoto (typeof BitmapeImage)。
样式在这里:
<Style x:Key="friendsListStyle" TargetType="{x:Type ListBox}">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Grid Name="RootLayout">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="60"></RowDefinition>
</Grid.RowDefinitions>
<Image Margin="4,4,4,2" Source="{Binding Path=ProfilePhoto}" Grid.Column="0"/>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
我收到此错误:
Must create DependencySource on same Thread as the DependencyObject.
at System.Windows.Markup.XamlReader.RewrapException(Exception e, Uri baseUri)
at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter)
at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlObjectWriter objectWriter)
at System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent(DependencyObject container, IComponentConnector componentConnector, IStyleConnector styleConnector, List`1 affectedChildren, UncommonField`1 templatedNonFeChildrenField)
at System.Windows.FrameworkTemplate.LoadContent(DependencyObject container, List`1 affectedChildren)
at System.Windows.StyleHelper.ApplyTemplateContent(UncommonField`1 dataField, DependencyObject container, FrameworkElementFactory templateRoot, Int32 lastChildIndex, HybridDictionary childIndexFromChildID, FrameworkTemplate frameworkTemplate)
at System.Windows.FrameworkTemplate.ApplyTemplateContent(UncommonField`1 templateDataField, FrameworkElement container)
at System.Windows.FrameworkElement.ApplyTemplate()
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Border.MeasureOverride(Size constraint)
如果我在列表框/列表框项上创建另一种样式,其中我仅绑定字符串或布尔属性,则效果很好。
仅当绑定 bitmapImage 属性时我才会遇到问题。
BitmapImage 属性初始化为:
ProfilePhoto = new BitmapImage(new Uri("http://pokec.azet.sk/vanes90?i9=1f104a294997", UriKind.RelativeOrAbsolute))
URI 是图片的 url 或文件的路径。
怎么了?感谢您的帮助和建议。
风格很好,只有当我不使用另一个线程中的方法调用刷新数据时它才有效。
I have problem with update listbox from view model class. I use Caliburn Micro framework. My scenario is here:
I bind property of type bindableCollection on listbox:
Code from view model:
private BindableCollection<UserInfo> _friends;
public BindableCollection<UserInfo> Friends
{
get { return _friends; }
set
{
_friends= value;
NotifyOfPropertyChange(()=>Friends);
}
}
In view model I create a fake service method which return new fresh data as List and with this data I update a property Friends which is bind on listbox.
I call fake service method in dispatcher timer tick event every 3 seconds.
private static UserInfo FakeUser()
{
var user = new UserInfo
{
Age = "16",
Emphasis = true,
IdUser = "11542",
IsBlocked = false,
IsFriend = true,
LocationInfo = new Location
{
CityName = "TN",
IdCity = 123456,
IdRegion = 1246,
RegionName = "TN",
},
StatusInfo = new Status
{
IdChat = 12,
IsLogged = true,
LastLogin = "153151",
IsChating = true,
RoomName = "Car",
},
ProjectStatusInfo = new ProjectStatus(),
IsIamFriend = true,
PlusInfo = new Plus(),
ProfilePhoto = new BitmapImage(new Uri("http://pokec.azet.sk/vanes90?i9=1f104a294997", UriKind.RelativeOrAbsolute))
};
return user;
}
private static IEnumerable<UserInfo> GetFakeFriends()
{
var list = new List<UserInfo>();
for (int i = 0; i < 20; i++)
{
list.Add(FakeUser());
}
return list;
}
private void DispatcherTimer_Tick(object sender, EventArgs eventArgs)
{
if (_isExecuting)
return;
_isExecuting = true;
new System.Threading.Tasks.Task(() =>
{
var freshFriends = GetFakeFriends();
Execute.OnUIThread((System.Action)(() =>
{
Friends.Clear();
foreach (var freshFriend in freshFriends)
{
Friends.Add(freshFriend);
}
}));
}).Start();
_isExecuting = false;
}
}
If I don't apply any style on listbox, it works good.
View:
<Grid>
<ListBox Name="Friends"
Grid.Row="2"
Margin="4,4,4,4">
</ListBox>
</Grid>
If I apply some style in which I bind property ProfilePhoto (typeof BitmapeImage) from UserInfo on listbox.
Style is here:
<Style x:Key="friendsListStyle" TargetType="{x:Type ListBox}">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Grid Name="RootLayout">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="60"></RowDefinition>
</Grid.RowDefinitions>
<Image Margin="4,4,4,2" Source="{Binding Path=ProfilePhoto}" Grid.Column="0"/>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
I get this error:
Must create DependencySource on same Thread as the DependencyObject.
at System.Windows.Markup.XamlReader.RewrapException(Exception e, Uri baseUri)
at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter)
at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlObjectWriter objectWriter)
at System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent(DependencyObject container, IComponentConnector componentConnector, IStyleConnector styleConnector, List`1 affectedChildren, UncommonField`1 templatedNonFeChildrenField)
at System.Windows.FrameworkTemplate.LoadContent(DependencyObject container, List`1 affectedChildren)
at System.Windows.StyleHelper.ApplyTemplateContent(UncommonField`1 dataField, DependencyObject container, FrameworkElementFactory templateRoot, Int32 lastChildIndex, HybridDictionary childIndexFromChildID, FrameworkTemplate frameworkTemplate)
at System.Windows.FrameworkTemplate.ApplyTemplateContent(UncommonField`1 templateDataField, FrameworkElement container)
at System.Windows.FrameworkElement.ApplyTemplate()
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Border.MeasureOverride(Size constraint)
If I make another style on listbox / listbox item, in which I bind only string or bool properties it works good.
I have problem only if bind bitmapImage property.
BitmapImage property is init as:
ProfilePhoto = new BitmapImage(new Uri("http://pokec.azet.sk/vanes90?i9=1f104a294997", UriKind.RelativeOrAbsolute))
URI is url of picture or path to the file.
What is wrong? Thank for help and advice.
Style is good, it work only if I don't refresh data with method call in another thread.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您在 UI 线程以外的任何线程上创建 BitmapImage,则可以解释此问题。您可以冻结 BitmapImage 以确保可以从任何线程访问它:
If you're creating the
BitmapImage
on any thread other than the UI thread, that would explain this issue. You can freeze theBitmapImage
to ensure it is accessible from any thread: