0

私の問題:犬の飼い主のリストボックスがあり、犬のリストボックスがあります。犬のリストボックス項目テンプレートを次のように変更したい: DogName(textblock)+DogKind(textblock)+Owners(combobox).最初の 2 つは成功しましたが、既存の所有者をコンボボックスに追加できません。コンボボックスに次のような名前を付けると:

<ComboBox x:Name="mycombo" />

c# コードに mycombo 変数が表示されません。XAML:

<Window x:Class="CodeFirst.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sajat="clr-namespace:CodeFirst"
        Title="MainWindow" Height="557.638" Width="721.294"
        >
<Grid x:Name="grid1"> 
<ListBox x:Name="listbox2" HorizontalAlignment="Left" Height="313" Margin="338,10,0,0" VerticalAlignment="Top" Width="250">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">                        
                        <TextBlock Text="{Binding Path=Name}"/>
                        <TextBlock Text=", "/>
                        <TextBlock Text="{Binding Path=Kind}"/>     
                        <ComboBox />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
</ListBox>     
</Grid>
</Window>

itemsource をコンボボックスに渡す方法、または所有者を追加するにはどうすればよいですか?

4

2 に答える 2

0

DataContext を使用する場合は、次のように Binding を設定できます。

<ComboBox ItemsSource="{Binding Path=DataContext.MyItemsSource, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"></ComboBox>
于 2013-04-02T16:39:03.557 に答える
0

まず、WPF またはその他の XAML ベースのテクノロジを使用するには、次のことを理解しておく必要があります。

UI はデータではありません。データはデータです。UIはUIです。

これはComboBox、コード内で UI 要素を操作してデータを入力するのではなく、 を作成してViewModelこれらのオブジェクトをバインドすることを意味します。

この例では、単純な例であるためそれWindow自体が使用されてViewModelいますが、すべてのアプリケーション ロジックを別のクラスに移動することを検討する必要があります。

<Window x:Class="MiscSamples.UIisNotData"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="UIisNotData" Height="300" Width="300">
    <UniformGrid Rows="1" Columns="2">
        <DockPanel>
            <TextBlock Text="Owners:" DockPanel.Dock="Top" FontWeight="Bold" TextAlignment="Center" Margin="2"/>
            <Button Content="Add" Width="80" DockPanel.Dock="Bottom" Margin="2" Click="AddOwner"/>

            <ListBox ItemsSource="{Binding Owners}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <TextBlock Text="{Binding Name}" x:Name="block"/>
                            <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Visibility="Collapsed" x:Name="box"/>
                        </Grid>
                        <DataTemplate.Triggers>
                            <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType=ListBoxItem}}" Value="True">
                                <Setter TargetName="block" Property="Visibility" Value="Collapsed"/>
                                <Setter TargetName="box" Property="Visibility" Value="Visible"/>
                            </DataTrigger>
                        </DataTemplate.Triggers>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </DockPanel>

        <DockPanel>
            <TextBlock Text="Dogs:" DockPanel.Dock="Top" FontWeight="Bold" TextAlignment="Center" Margin="2"/>
            <ListBox ItemsSource="{Binding Dogs}" HorizontalContentAlignment="Stretch">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <DockPanel>
                            <ComboBox ItemsSource="{Binding DataContext.Owners, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
                                      SelectedItem="{Binding Owner}" DisplayMemberPath="Name"
                                      DockPanel.Dock="Right" Width="100"/>
                            <TextBlock>
                                <Run Text="{Binding Name}"/>
                                <Run Text=", "/>
                                <Run Text="{Binding Kind}"/>
                            </TextBlock>
                        </DockPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </DockPanel>
    </UniformGrid>
</Window>

コード ビハインド(このコードは ViewModel に配置する必要があります) :

public partial class UIisNotData : Window
    {
        public ObservableCollection<Owner> Owners { get; set; }
        public ObservableCollection<string> Kinds { get; set; }
        public ObservableCollection<Dog> Dogs { get; set; } 

        public UIisNotData()
        {
            InitializeComponent();

            Owners = new ObservableCollection<Owner>
                {
                    new Owner() {Name = "Jack"},
                    new Owner() {Name = "Mike"},
                    new Owner() {Name = "Kirk"},
                    new Owner() {Name = "John"},
                };

            Kinds = new ObservableCollection<string>
                {
                    "Affenpinscher",
                    "Afghan Hound",
                    "Airedale Terrier",
                    "Akita"
                    //.. All the rest of dog Breeds taken from http://www.petmd.com/dog/breeds?breed_list=az#.UVsQKpPcmQo
                };

            Dogs = new ObservableCollection<Dog>
                {
                    new Dog() {Name = "Bobby", Kind = Kinds[0], Owner = Owners[0]},
                    new Dog() {Name = "Fido", Kind = Kinds[1], Owner = Owners[1]},
                    new Dog() {Name = "Toby", Kind = Kinds[2], Owner = Owners[2]}
                };

            DataContext = this;
        }

        private void AddOwner(object sender, RoutedEventArgs e)
        {
            Owners.Add(new Owner(){Name = "New Owner"});
        }
    }

データ・モデル:

    public class Owner : PropertyChangedBase
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                OnPropertyChanged("Name");
            }
        }
    }

    public class Dog: PropertyChangedBase
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                OnPropertyChanged("Name");
            }
        }

        private Owner _owner;
        public Owner Owner
        {
            get { return _owner; }
            set
            {
                _owner = value;
                OnPropertyChanged("Owner");
            }
        }

        private string _kind;
        public string Kind
        {
            get { return _kind; }
            set
            {
                _kind = value;
                OnPropertyChanged("Kind");
            }
        }
    }

PropertyChangedBase クラス:

public class PropertyChangedBase:INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

結果:

ここに画像の説明を入力

この例については、次の 3 つの重要な側面を考慮する必要があります。

  • コードで UI 要素を操作しているわけではありません。ほとんどの場合、これは WPF では完全に不要です。
  • データ モデルのクラスは、INotifyPropertyChangedWPF で双方向バインディングをサポートするために実装されます。
  • ObservableCollection<T>コレクションは、要素がコレクションに追加/削除されたときの自動通知をサポートするためのタイプです(ListBoxesなどを自動的に更新するため)。

もう 1 つお気づきかもしれませんが、この例の XAML 要素には特定のサイズやMargin値がありません。のようなものMargin="338,10,0,0"は通常、Visual Studio デザイナーから得られるものであり、構造化されていないレイアウトを示しています。WPF のレイアウト要素 ( DockPanelStackPanelGridUniformGridWrapPanelなど) を確認し、デザイナーを使用する代わりに XAML のコーディングを開始することをお勧めします。これにより、はるかに高いレベルのスケーラビリティが可能になり、固定位置要素のニュアンスからも解放されます。

于 2013-04-02T17:39:42.090 に答える