1

したがって、私はWPFデータバインディングにまったく慣れていません..複雑です。この時点で、事前に作成されたテスト項目のリストを作成し、ボタンを押したときにデータ テンプレートを含むリスト ボックスに表示しようとしています。チュートリアルと MSDN で何時間も頭を悩ませた後、これが私が思いついた最高のものです。

リストを作成したいデータ項目:

class ListingItem
{
    private string title;
    private string user;
    private string category;

    //Dummy constructor for test purposes
    public ListingItem()
    {
        title = "TestTitle";
        user = "TestUser";
        category = "TestCatagory";
    }
}

手っ取り早いリスト作成者:

class ListMaker
{
    public static List<ListingItem> getListing()
    {
        List<ListingItem> listing = new List<ListingItem>();
        for(int i = 0; i <100; i++)
        {
            listing.Add(new ListingItem());
        }
        return listing;
    }
}

リスト自体の XAML:

<ListBox x:Name="Listing">
<ListBox.ItemTemplate>
    <DataTemplate>
        <StackPanel Orientation="Vertical">
            <StackPanel Orientation="Horizontal">
                <TextBlock Foreground="Gray" Margin="25,0,0,0" Text="{Binding user}"/>
                <TextBlock Foreground="Gray" Margin="25,0,0,0" Text="{Binding category}"/>
            </StackPanel>
            <TextBlock Foreground="Black" Width="270" TextWrapping="Wrap" Text="{Binding title}"/>
        </StackPanel>
    </DataTemplate>
</ListBox.ItemTemplate>

そして最後に、魔法を起こすために想定されているボタンクリックイベント:

private void TabClickEvent(object sender, RoutedEventArgs e)
    {
        Listing.DataContext = RedditScanner.getListing();
    }

問題は、明らかに、魔法が起こっていないことです。エラーや簡単なものはありません。そのボタンを押すだけで、リスト ボックスに変更が表示されません。これについて何か助けはありますか?

4

4 に答える 4

2

プライベート フィールドにバインドすることはできません。公共の場でさえないと思います。

プロパティを使用します:

class ListingItem
{
    //private string title;
    //private string user;
    //private string category;

    public string Title { get; set; }
    public string User { get; set; }
    public string Category { get; set; }

    //Dummy constructor for test purposes
    public ListingItem()
    {
        Title = "TestTitle";
        User = "TestUser";
        Category = "TestCatagory";
    }
}

また、完全なデータバインディングを行うには、 onに実装 する必要があります。INotifyPropertyChangedListingItem

魔法は起こっていません。エラーや簡単なことは何もありません。

実行中は出力ウィンドウに注意してください。バインディング エラーが報告されます。

于 2013-08-23T22:42:47.310 に答える
1

以下で説明するように、コードに小さな変更を加えました。


class ListingItem
    {
        public  string title { get; set; }
        public string user { get; set; }
        public string category { get; set; }
    
        //Dummy constructor for test purposes
        public ListingItem()
        {
            title = "TestTitle";
            user = "TestUser";
            category = "TestCatagory";
        }
    }
  • リスト アイテム クラスは、タイトル、ユーザー、カテゴリをプロパティ(get;set;) に変更しました。また、バインディングを介してアクセスできるように、それらを公開する必要もありました。

    class ListMaker
    {
        public static List getListing()
        {
            List listing = new List();
            for (int i = 0; i < 100; i++)
            {
                listing.Add(new ListingItem());
            }
            return listing;
        }
    }
  • ListMaker クラスに変更はありません

    public class CommandHandler : ICommand
    {
        private Action _action;
        private bool _canExecute;
        public CommandHandler(Action action, bool canExecute=true)
        {
            _action = action;
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            _action();
        }
    }
  • ボタンをバインドできる新しいクラスを導入しました。比較的一般的な場合、この種のクラス

<Window x:Class="SimpleDatabinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewmodel="clr-namespace:SimpleDatabinding"
Title="MainWindow" Height="350" Width="525">

<Window.DataContext>
<viewmodel:MainWindowViewModel/>
</Window.DataContext>

<Grid>
<DockPanel>
<Button Command="{Binding FillListCommand}" DockPanel.Dock="Top">Fill List</Button>

<ListBox ItemsSource="{Binding Listing}" DockPanel.Dock="Top">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Foreground="Gray" Margin="25,0,0,0" Text="{Binding user}"/>
<TextBlock Foreground="Gray" Margin="25,0,0,0" Text="{Binding category}"/>
</StackPanel>
<TextBlock Foreground="Black" Width="270" TextWrapping="Wrap" Text="{Binding title}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</Grid>
</Window>

  • xmlns:viewmodel="clr-namespace:SimpleDatabinding"が追加されていることに注意してください。SimpleDatabinding はプロジェクトの名前でした。以下のデータコンテキストでビューモデルを見つけるために使用されます。
  • Window.DataContext は、WPF ページをビュー モデルにバインドします。クラスを MainWindowViewModel と呼びました (以下を参照)。これにより、ビュー モデルのインスタンスが自動的に作成され、ウィンドウにバインドされます。
  • クリックするボタンを導入しました。コマンドFillListCommandにバインドされています。以下のビューモデルでそれを定義します。
  • ListBoxのItemsSourceを更新して、 Listingプロパティにバインドしました。
  • それ以外は同じだと思います。



class MainWindowViewModel : INotifyPropertyChanged 
{
    public event PropertyChangedEventHandler PropertyChanged;

    public List Listing { get; set; }
    public CommandHandler FillListCommand { get; set; }

    public MainWindowViewModel()
    {
        FillListCommand = new CommandHandler(DoFillList);
    }

    public void DoFillList()
    {
        Listing = ListMaker.getListing();
        ProperyHasChanged("Listing");
    }

    private void ProperyHasChanged(string propertyName)
    {
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
   
}

  • 最後に、viewmodel クラスにINotifyPropertyChangedインターフェイスを実装しました。これは、ビュー モデルの値が変更されたことを UI に通知するメカニズムです。ほとんどの実装では、これはある種の ViewModel 基本クラスにラップされていますが、見やすいように残しました。
  • 上記のように、Listing変数をパブリック プロパティ (get;set;) に変換して、バインディングを通じてアクセスできるようにしました。
  • FillListCommandというCommandHandlerプロパティを作成しました。これは上記のクラスを使用します。ボタンはこの変数にバインドされています。ビュー モデルのコンストラクターは、ボタンがクリックされたときに呼び出される関数を初期化し、それをポイントします。
  • 最後に、DoFillList関数で、Listingを初期化しますが、通知を使用して変更されたことを UI に知らせます。

いろいろ書いてすみません。これが多少役立つことを願っています。あなたが持っていたものとあまり変わらないと思います。

于 2013-08-24T01:00:09.953 に答える