C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[1]: TabControlのコンテンツにRunを配置したい


(過去ログ 76 を表示中)

[トピック内 2 記事 (1 - 2 表示)]  << 0 >>

■45122 / inTopicNo.1)  TabControlのコンテンツにRunを配置したい
  
□投稿者/ ryo (1回)-(2009/12/31(Thu) 05:17:55)

分類:[.NET 全般] 

はじめまして。
Visual C# 2008 Express Editionで開発をしております。

データ配列をバインドしたTabControlの中にRunを配置し、要素ごとの値をRunに表示したいと考えています。
サイトを調べたりして作ってみたのですが、フォーム表示後タブを切り替えると下記の例外が発生してしまいます。
 「コレクションは変更されています。列挙操作は実行されない可能性があります。」
何か分かる方が居られましたらご教授お願い致します。

現在の実装ですが、
1.要素毎の値をRunに表示するため、Runを継承したBindableRunクラスを作りBindableTextプロパティを持たせている。
  (RunのTextプロパティがDependencyPropertyではない為。)
2.BindableRunを、TabControlのContentTemplateへ配置している。

以下は原因調査用に簡略化したソースで、適当に作ったListBoxをバインディングのソースにしています。
宜しくお願いいたします。


[Window1.xaml]
<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="Window1" Height="300" Width="300">
    <DockPanel>
        <ListBox Height="100" Name="listBox1" DockPanel.Dock="Top" />
        <TabControl Name="tabControl1" ItemsSource="{Binding ElementName=listBox1, Path=Items}">
            <TabControl.ContentTemplate>
                <DataTemplate>
                    <TextBlock>
                        <TextBlock.Inlines>
                            <local:BindableRun BindableText="{Binding}" />
                        </TextBlock.Inlines>
                    </TextBlock>
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>
    </DockPanel>
</Window>

[Window1.xaml.cs]
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            listBox1.ItemsSource = new string[] { "ABC", "123", "あいう" };
        }
    }

[BindableRun.cs]
    public class BindableRun : Run
    {
        public string BindableText
        {
            get { return (string)GetValue(BindableTextProperty); }
            set { SetValue(BindableTextProperty, value); }
        }

        public static readonly DependencyProperty BindableTextProperty =
            DependencyProperty.Register("BindableText", 
                typeof(string), 
                typeof(BindableRun), 
                new UIPropertyMetadata(String.Empty, BindableTextChanged));

        private static void BindableTextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            Run run = (Run)sender;
            run.Text = (string)e.NewValue;
        }
    }

引用返信 編集キー/
■45147 / inTopicNo.2)  Re[1]: TabControlのコンテンツにRunを配置したい
□投稿者/ ryo (2回)-(2010/01/03(Sun) 03:40:09)
書き忘れていましたが、WPFになります。

結構長いこと悩んでいたのですが、
以下のサイトにどんぴしゃの内容で原因と回避策が載っておりました…。
http://msdn.microsoft.com/ja-jp/magazine/dd569761.aspx

発生条件は、上記のようにバインド可能なフロードキュメント要素クラスを作って、
かつDataContext(継承された依存関係プロパティ)を使用した場合に例外になるそうです。
フロードキュメント要素をバインドする方法は上記コードのようなものしか知らないのでよくハマりそうです…。

回避策としては、先祖のFrameworkElemntのDataContextに直接バインドするというやり方が紹介されていました。
BindableRunのコンストラクタで実行したら例外は発生しなくなりました。
どうもお騒がせ致しました。

    public BindableRun()
    {
        FixupDataContext(this);
    }

    public static void FixupDataContext(FrameworkContentElement element)
    {
        Binding b = new Binding(FrameworkContentElement.DataContextProperty.Name);
        b.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(FrameworkElement), 1);
        element.SetBinding(FrameworkContentElement.DataContextProperty, b);
    }

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -