wpf multithreading dispatcher bitmapimage

wpf - XAML enlazar propiedad BitmapImage ViewModel



multithreading dispatcher (1)

Si está creando BitmapImage en un subproceso que no sea el subproceso de la interfaz de usuario, eso explicaría este problema. Puede congelar BitmapImage para asegurarse de que sea accesible desde cualquier hilo:

var bitmapImage = new BitmapImage(...); bitmapImage.Freeze();

Tengo problemas con la actualización del cuadro de lista de la clase de modelo vista. Yo uso Caliburn Micro Framework. Mi escenario está aquí:

Ato propiedad de tipo bindableCollection en el cuadro de lista:

Código desde modelo de vista:

private BindableCollection<UserInfo> _friends; public BindableCollection<UserInfo> Friends { get { return _friends; } set { _friends= value; NotifyOfPropertyChange(()=>Friends); } }

En el modelo de vista, creo un método de servicio falso que devuelve nuevos datos nuevos como Lista y con estos datos actualizo la propiedad Amigos, que está vinculada en el cuadro de lista.

Llamo al método de servicio falso en el evento de tick temporizador del despachador cada 3 segundos.

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; } }

Si no aplico ningún estilo en el cuadro de lista, funciona bien.

Ver:

<Grid> <ListBox Name="Friends" Grid.Row="2" Margin="4,4,4,4"> </ListBox> </Grid>

Si aplico algún estilo en el que vinculo la propiedad ProfilePhoto (typeof BitmapeImage) de UserInfo en el cuadro de lista.

El estilo está aquí:

<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>

Me sale este 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)

Si hago otro estilo en el cuadro de lista / elemento de cuadro de lista, en el cual solo ato propiedades de cadena o bool funciona bien.

Tengo problema solo si vinculo la propiedad bitmapImage.

La propiedad BitmapImage es init como:

ProfilePhoto = new BitmapImage(new Uri("http://pokec.azet.sk/vanes90?i9=1f104a294997", UriKind.RelativeOrAbsolute))

URI es la url de la imagen o la ruta al archivo.

¿Qué está mal? Gracias por la ayuda y el consejo.

El estilo es bueno, funciona solo si no actualizo los datos con la llamada al método en otro hilo.