XAML bind propriété BitmapImage ViewModel

j'ai un problème avec la liste de mise à jour de la classe view model. J'utilise Caliburn Micro framework. Mon scénario est ici:

je lier la propriété de type bindableCollection sur la zone de liste:

Code à partir du modèle de vue:

private BindableCollection<UserInfo> _friends;

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

Dans la vue modèle, je créer de faux méthode de service qui de retour de nouvelles données sous forme de Liste et avec ces données, je l'ai mise à jour de la propriété Amis qui est lié sur la zone de liste.

j'appelle la méthode de service de faux dans le chronomètre du répartiteur événement toutes les 3 secondes.

 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 je n'applique aucun style sur listbox, cela fonctionne bien.

Vue:

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

si j'applique un style dans lequel je lie la propriété ProfilePhoto (typeof BitmapeImage) à partir de UserInfo sur listbox.

le Style est ici:

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

j'ai cette erreur:

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 je crée un autre style sur un élément listbox / listbox, dans lequel je ne lie que des propriétés string ou bool il fonctionne bon.

Je n'ai de problème que si bind propriété bitmapImage.

BitmapImage propriété is init as:

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

URI est l'url de l'image ou du chemin vers le fichier.

Quel est le problème? Merci pour l'aide et des conseils.

le Style est bon, ça marche seulement si je ne suis pas d'actualiser les données avec l'appel de la méthode dans un autre thread.

30
demandé sur Simon Fox 2011-01-16 16:58:48

1 réponses

si vous créez le BitmapImage sur tout autre fil que le fil UI, cela expliquerait ce problème. Vous pouvez congeler les BitmapImage pour s'assurer qu'il est accessible à partir de n'importe quel thread:

var bitmapImage = new BitmapImage(...);
bitmapImage.Freeze();
71
répondu Kent Boogaart 2011-09-27 14:57:35