2011-01-16 2 views
30

뷰 모델 클래스에서 업데이트 목록 상자에 문제가 있습니다. Caliburn Micro 프레임 워크를 사용합니다. 내 시나리오는 여기에 있습니다 : 뷰 모델XAML bind BitmapImage ViewModel 속성

코드 : 뷰 모델에서

private BindableCollection<UserInfo> _friends; 

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

내가 만드는 가짜 서비스 방법은 느릅 나무 새로운 신선한 데이터를 반환

내가 목록 상자에 입력합니다 bindableCollection의 속성을 바인딩 목록 및이 데이터를 사용하여 목록 상자에서 바인딩되는 속성 친구를 업데이트합니다.

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> 

나는 목록 상자에 사용자 정보에서 속성 ProfilePhoto (대해서 typeof BitmapeImage)를 결합하는 몇 가지 스타일을 적용합니다.

스타일은 여기에 있습니다 : 나는 느릅 나무에서, 목록 상자/목록 상자 항목에 다른 스타일을 한 경우

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) 

내가 그것을 잘 작동에만 문자열 또는 부울 속성을 바인딩 :

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

나는이 오류 .

bind bitmapImage 속성에만 문제가 있습니다.

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

URI가 파일에 그림이나 경로의 URL은 다음과 같이

BitmapImage 속성은 init이된다.

무엇이 잘못 되었나요? 도움과 조언에 감사드립니다.

스타일이 좋으면 다른 스레드에서 메서드 호출로 데이터를 새로 고치지 않는 경우에만 작동합니다.

답변

71

UI 스레드가 아닌 다른 스레드에서 BitmapImage을 만드는 경우이 문제가 설명됩니다. 당신은 어떤 스레드에서 액세스 할 수 있도록하기 위해 BitmapImage을 동결 할 수 있습니다 도움을

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

씨 Boogaart의 감사가, 문제가 해결된다. –

+5

좋아요! 어떻게 찾았 니? –

+0

'BitmapImage'는'System.Windows.Freezable'에서 상속되었습니다. - "고정 된 Freezable은 고정되어 있지 않은 Freezable은 공유 할 수 없지만 스레드간에 공유 될 수 있습니다." - http://msdn.microsoft.com/en-us/library/ms750509(v=vs.110).aspx – codekaizen