0

これは、stackoverflow への私の最初の投稿です。何か間違ったことをした場合は、お詫び申し上げます。Prism と MVVM パターンを利用する WPF アプリケーションがあります。私の見解では、カスタム データ テンプレートを持ち、ShippingLabel というクラスの ObservableCollection にバインドされている TabControl があります。

TabControl の Xaml:

<TabControl Grid.Row="2" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" ItemsSource="{Binding Path=ShippingLabels}">
            <TabControl.ItemTemplate>
                <DataTemplate>
                    <Label Content="{Binding Path=Name}"/>
                </DataTemplate>
            </TabControl.ItemTemplate>
            <TabControl.ContentTemplate>
                <DataTemplate>
                    <StackPanel>
                        <Image Source="{Binding Path=Image}"/>
                    </StackPanel>
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>

TabControl にバインドするために作成したヘルパー クラス

public class ShippingLabel
{
/// <summary>
/// Name of the image, this is the text that will be displayed in the Tab
/// </summary>
public string Name { get; set; }
/// <summary>
/// BitmapImage to display for TabContent
/// </summary>
public BitmapImage Image { get; set; }
}

最初は、ViewModel のコンストラクターで必要なすべての作業を行っていました。ViewModel は WCF サービスを呼び出し、base64 でエンコードされた文字列形式の配送ラベルを含む応答を返します。これは問題なく機能し、ラベルは、出荷中であることを示したパッケージの数に基づいて正しく表示されました. ユーザビリティを改善するために、サービスの呼び出しを処理し、ワーカーが完了したら配送ラベルを処理する BackgroundWorker を追加することにしました。

BackgroundWorker イベント

private void serviceWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
  //Present the shipping labels
  ShippingLabels = new ObservableCollection<ShippingLabel>();
  int packageNumber = 0;
  foreach (var result in adapter.CurrentResponse.PackageResults)
  {
    packageNumber++;

    Byte[] labelBytes = new Byte[result.ShippingLabel.Length];
    labelBytes = Convert.FromBase64String(result.ShippingLabel.Replace("\r\n", "").Replace(" ", ""));

    var tempLabel = new BitmapImage();
    tempLabel.BeginInit();
    tempLabel.StreamSource = new MemoryStream(labelBytes);
    tempLabel.Rotation = Rotation.Rotate90;
    tempLabel.EndInit();

    ShippingLabels.Add(new ShippingLabel()
    {
      Name = "Package " + packageNumber.ToString(),
      Image = tempLabel
    });
  }

  ShowBusyIndicator = false;
  RaisePropertyChanged(() => ShippingLabels);
}

private void serviceWorker_DoWork(object sender, DoWorkEventArgs e)
{
  adapter.ProcessShipment();
}

ただし、これを試してみると、UI には名前の付いたタブのみが表示され、タブのコンテンツには画像が表示されません。私は自分のクラスが INotifyPropertyChanged をサポートするようにしようとしましたが、それは何かがあると思っていましたが、違いはありませんでした。問題は、コレクションの Image プロパティが更新されるように変更されたことを UI に正しく通知するには、何をする必要があるかということです。

4

1 に答える 1

1

ラベルの名前が表示されていることに気付いたので、これはおそらく画像自体に固有のものです。バインディングはきれいに見えます。

画像がバックグラウンド ワーカーで作成されている場合は、非常に注意する必要があり、スレッド アフィニティがあり、バックグラウンドで画像を読み込むのBitmapImageは比較的複雑です。転送するには凍結する必要があります。

どこかのバックグラウンド ワーカーによって飲み込まれている例外はありませんか?

于 2011-04-05T15:40:18.283 に答える