2011-01-16 17 views
30

Mam problem z listbox aktualizacji z widoku modelu klasy. Używam frameworka Caliburn Micro. Mój scenariusz jest tutaj:Wiązanie XAML BitmapImage Właściwość ViewModel

wiążę właściwość typu bindableCollection na listbox:

kod z widoku modelu

private BindableCollection<UserInfo> _friends; 

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

w świetle modelu Tworzę fałszywe metoda usługa wich zwracają nowe świeże dane jako Lista i za pomocą tych danych aktualizuję właściwość Przyjaciele, która jest powiązana z listbox.

Wywołuję fałszywą metodę usługi w teście licznika czasu dyspozytora co 3 sekundy.

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

    } 

Jeśli nie stosuję żadnego stylu na liście list, działa dobrze.

Widok:

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

Gdybym zastosować jakiś styl, w którym wiążę ProfilePhoto posesji (typeof BitmapeImage) z userinfo na listbox.

Style jest tutaj:

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

otrzymuję ten błąd:

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) 

Jeśli zrobię inny styl na pozycji listbox/listbox w wich wiążę tylko właściwości ciąg lub bool to działa dobrze .

Mam problem tylko w przypadku powiązania właściwości bitmapImage.

nieruchomość BitmapImage jest init, jak:

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

URI jest URL obrazu lub ścieżkę do pliku.

Co jest nie tak? Dziękuję za pomoc i porady.

Styl jest dobry, działa tylko wtedy, gdy nie odświeżam danych wywołaniem metody w innym wątku.

Odpowiedz

71

Jeśli tworzysz BitmapImage w dowolnym wątku innym niż wątek interfejsu użytkownika, to wyjaśniałoby to problem. Możesz zablokować BitmapImage, aby mieć pewność, że jest dostępny z dowolnego wątku:

+0

Panie Boogaart, dziękuję za pomoc, problem został rozwiązany. –

+5

Świetnie! Jak to odkryłeś? –

+0

Ponieważ 'BitmapImage' dziedziczy po' System.Windows.Freezable' - "Zablokowane zamrożenie może być współużytkowane przez wątki, podczas gdy niezamarznięty Freezable nie może". - http://msdn.microsoft.com/en-us/library/ms750509(v=vs.110).aspx – codekaizen

Powiązane problemy