0

私はMVVMサンプルアプリに取り組んでいます。VSC# 2010 のソリューション内に 2 つのプロジェクトがあります。1 つのプロジェクト (メイン プロジェクト) には、右側と左側にある 2 つのグリッドを持つ mainwindow.xaml があります。左側のグリッドには、observablecollection<> の助けを借りて項目を含む listBox があります。たとえば、電圧、I2C などが項目です。selecteditemリストボックスのプロパティも設定しましたselecteditem

私の主なクエリは、デフォルトで追加された1つのアイテム( "CONNECT")を持つTABCONTROLを持つ右側のグリッドです。私が必要とするのは、listBox から「Voltage」項目を選択したときに、tabcontrol 内に tabitem (egVoltage タブ) を追加することです。

私のグリッド内のTabControlとListBox:

<Grid Grid.Column="0" Name="BoardTabSelect" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
            <ListBox Name="ButtonPanel" Style="{DynamicResource styleBanner}" ItemsSource="{Binding BoardTabs, Mode=TwoWay}" SelectedItem="{Binding SelectedTab, Mode=TwoWay}" >
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Name="BoardtabChanger" Margin="53,27,0,0" Text="{Binding TabOperation}" />
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </Grid>         

私のタブコントロール:

                <Grid Grid.Row="0" >
                    <TabControl Name="ConnectTab" Style="{DynamicResource styleBackground}">
                        <tablocal:CloseableTabItem Header="Connect" x:Name="ConnectMain" MouseDoubleClick="TabItem_MouseDoubleClick"> 
                            <DockPanel>
                                <ListView  Name="listView" Height="460" Margin="0,-77,0,0" ItemsSource="{Binding Products}" SelectedItem="{Binding SelectedProduct, Mode=TwoWay}">
                                    <ListView.View>
                                        <GridView>
                                            <GridViewColumn Width="300" Header="Name" DisplayMemberBinding="{Binding Name}" />
                                            <GridViewColumn Width="283" Header="Connection Status" DisplayMemberBinding="{Binding Connection_Status}" />
                                        </GridView>
                                    </ListView.View>
                                </ListView>

                                <Button Content="Connect" Height="23" HorizontalAlignment="Stretch" Margin="-920,500,0,0" Name="ConnectBtnGrid" VerticalAlignment="Stretch" Width="100" Command="{Binding Path=ConnectCommand}" />
                                <Button Content="Update MSP430" Height="23" HorizontalAlignment="Stretch" Margin="-560,500,0,0" Name="UpdateMSPBtn" VerticalAlignment="Stretch" Width="100" />
                                <Button Content="Disconnect" Height="23" HorizontalAlignment="Stretch" Margin="-220,500,0,0" Name="DisconnectBtn" VerticalAlignment="Stretch" Width="100" Command="{Binding Path=DisconnectCommand}" />
                            </DockPanel>
                       </tablocal:CloseableTabItem>
                    </TabControl>
                </Grid>                 

私のViewModelクラスはここにあります:

public List<Product> m_Products;
    public ObservableCollection<Product> m_BoardTabs;        

    public ProductViewModel()
    {           
        m_Products = new List<Product>()
        {                
            new Product() {Name = "Bavaria", Connection_Status = "Disconnected"},
            new Product() {Name = "Redhook", Connection_Status = "Disconnected"},                
        };

        m_BoardTabs = new ObservableCollection<Product>()
        {
            new Product() {TabOperation = "Connect"}              
        };
    }                      

    public List<Product> Products
    {
        get
        {
            return m_Products;
        }

        set
        {
            m_Products = value;
        }
    }

    public ObservableCollection<Product> BoardTabs
    {
        get
        {
            return m_BoardTabs;
        }

        set
        {
            m_BoardTabs = value;
        }
    }

    /// <summary>
    /// get:
    /// set:   
    /// </summary>
    private Product m_SelectedItem;
    public Product SelectedProduct
    {
        get
        {
            return m_SelectedItem;
        }

        set
        {
            m_SelectedItem = value;                
            NotifyPropertyChanged("SelectedProduct");
        }
    }

    private Product m_SelectedTab;
    public Product SelectedTab
    {
        get
        {
            return m_SelectedTab;
        }

        set
        {
            m_SelectedTab = value;
            NotifyPropertyChanged("SelectedTab");
            onTabChanged();
        }
    }        

    void onTabChanged()
    {
        if (SelectedTab.TabOperation == "Voltage")
        {
            //Add tab here
        }
    }

    public Product value { get; set; }

    /// <summary>
    /// get:
    /// set:   
    /// </summary>
    private ICommand mUpdater;
    public ICommand ConnectCommand
    {
        get
        {
            if (mUpdater == null)
                mUpdater = new DelegateCommand(new Action(SaveExecuted), new Func<bool>(SaveCanExecute));

            return mUpdater;
        }
        set
        {
            mUpdater = value;                
        }
    }

    public bool SaveCanExecute()
    {
        return true;
    }     

    public void SaveExecuted()
    {
        if (SelectedProduct.Connection_Status == "Disconnected" && SelectedProduct.Name == "Bavaria")
        {
            SelectedProduct.Connection_Status = "Connected";
            m_BoardTabs.Add(new Product() { TabOperation = "I2C" });
            m_BoardTabs.Add(new Product() { TabOperation = "Voltage" });
            m_BoardTabs.Add(new Product() { TabOperation = "Clock" });
            m_BoardTabs.Add(new Product() { TabOperation = "Codec" });
            m_BoardTabs.Add(new Product() { TabOperation = "EEPROM" });                             
        }

        else if (SelectedProduct.Connection_Status == "Disconnected" && SelectedProduct.Name == "Redhook")
        {
            SelectedProduct.Connection_Status = "Connected";

            m_BoardTabs.Add(new Product() { TabOperation = "I2C" });
            m_BoardTabs.Add(new Product() { TabOperation = "Voltage" });
            m_BoardTabs.Add(new Product() { TabOperation = "Clock" });
            m_BoardTabs.Add(new Product() { TabOperation = "Codec" });
            m_BoardTabs.Add(new Product() { TabOperation = "EEPROM" });
            m_BoardTabs.Add(new Product() { TabOperation = "PCM Route" });
            m_BoardTabs.Add(new Product() { TabOperation = "PCM Route #" });
            m_BoardTabs.Add(new Product() { TabOperation = "PCM Gen" });
            m_BoardTabs.Add(new Product() { TabOperation = "SD Card" });
            m_BoardTabs.Add(new Product() { TabOperation = "FPGA" });
            m_BoardTabs.Add(new Product() { TabOperation = "PCMPDM" });
            m_BoardTabs.Add(new Product() { TabOperation = "Data Gen" });           
        }
    }        

私のコントロールに追加したいタブアイテム「VOLTAGE」は、最初に述べた別のプロジェクトの一部です。独自のビュー、ビューモデル、およびモデル クラスがあります。以下は、追加したい in.xaml ファイルのビューです。

<Grid Name="VoltageTab" Height="572" Width="590" DataContext="{StaticResource VoltageViewModel}" >
    // Some UI componments which shud be placed inside VOLTAGE Tab on selecting Voltage from ListBox.
</Grid>

上記のように、ユーザーが ListBox から Voltage アイテムをクリックすると作成される VoltageTab 内に上記のビューを配置したいと考えています。

4

2 に答える 2

0

タブ コントロールのデータ テンプレートには、タブアイテムを含めないでください。tabcontrol は、バインドされた Collection 内の各要素の tabitem を生成しています。tabitem ヘッダーへのデータバインディングを有効にするには、tabcontrol の itemcontainerstyle プロパティを設定します。ここに小さなサンプルがあります:

景色:

<Window x:Class="WpfLab.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="0.5*"/>
        <ColumnDefinition Width="0.5*"/>
    </Grid.ColumnDefinitions>
    <TabControl ItemsSource="{Binding ProductTabs}">
        <TabControl.ItemContainerStyle>
            <Style TargetType="TabItem">
                <Setter Property="Header" Value="{Binding Header}"/>
            </Style>
        </TabControl.ItemContainerStyle>
    </TabControl>
    <ListBox Grid.Column="1" ItemsSource="{Binding Products}" SelectedItem="{Binding SelectedProduct}"/>
</Grid>

ビューモデル

using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;

namespace WpfLab
{
    public partial class MainWindow : Window
    {
        Product selectProduct;

        public MainWindow()
        {
            InitializeComponent();

            Products = new ObservableCollection<Product>();
            ProductTabs = new ObservableCollection<Product>();

            var products = Enumerable.Range(0, 10).Select(i => new Product { Header = "Product " + i });
            foreach (var p in products)
                Products.Add(p);

            DataContext = this;
        }

        public Product SelectedProduct 
        {
            get { return this.selectProduct; }

            set
            {
                UpdateTabs(this.selectProduct, value);
                this.selectProduct = value;
            }
        }

        public ObservableCollection<Product> Products { get; private set; }

        public ObservableCollection<Product> ProductTabs { get; private set; }

        void UpdateTabs(Product old, Product @new)
        {
            if (ProductTabs.Any(p => p == old))
                ProductTabs.Remove(old);

            ProductTabs.Add(@new);
        }
    }

    public class Product
    {
        public string Header { get; set; }

        public override string ToString()
        {
            return Header;
        }
    }
}
于 2012-09-21T10:03:50.090 に答える
0

TabControl には ItemsSource プロパティがあります。これは、ViewModel からの監視可能なオブジェクトのコレクションにバインドできます。

これに加えて、観察可能なコレクションで使用されているオブジェクトには、TabItem である関連する DataTemplate が必要です。

その結果、DataTemplate を使用して TabControl のソースとして機能する ObservableCollection にオブジェクトを追加すると、新しい TabItem が TabControl に追加されます。

また、最初の tabitem の observablecollection に 1 つのエントリ/オブジェクトがあることを確認してください。

適切な名前空間/参照を追加することで、DataTemplate の他のプロジェクトから TabItem を参照できます。

これがViewModelクラスです

 public class TabItemDetail
{
    public string Header { get; set; }
}

public class MainWindowViewModel : INotifyPropertyChanged
{
    #region Members

    List<string> _dataSource = null;
    string _selectedDataSource = null;
    ObservableCollection<TabItemDetail> _tabItems = null;

    #endregion

    #region INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

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

    #endregion

    public ObservableCollection<TabItemDetail> Items
    {
        get
        {
            if (_tabItems == null)
            {
                _tabItems = GetTabItems();
            }

            return _tabItems;
        }
    }

    public List<string> DataSource
    {
        get
        {
            if (_dataSource == null)
            {
                _dataSource = GetDataSource();
            }

            return _dataSource;
        }
    }

    public string SelectedDataSource
    {
        get { return _selectedDataSource; }
        set
        {
            if (_selectedDataSource == value)
                return;

            _selectedDataSource = value;

            AddItemsToTab(value);

            OnPropertyChanged("SelectedDataSource");
        }
    }


    #region Private methods

    private void AddItemsToTab(string selectedItem)
    {
        if (_tabItems != null && _tabItems.Count > 0)
        {
            var query = from item in _tabItems
                        where item.Header == selectedItem
                        select item;

            if (query.Count() == 1)
                return;
            else
                _tabItems.Add(new TabItemDetail { Header = selectedItem });
        }
    }

    private List<string> GetDataSource()
    {
        List<string> source = new List<string>();

        source.Add("Default tab");
        source.Add("Voltage Tab");

        return source;
    }

    private ObservableCollection<TabItemDetail> GetTabItems()
    {
        ObservableCollection<TabItemDetail> newSource = new ObservableCollection<TabItemDetail>();
        newSource.Add(new TabItemDetail { Header = "Connect" });

        return newSource;
    }

    #endregion
}

ここにビューがあります

  <Window x:Class="SampleApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:SampleApp"

    Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>
<Window.Resources>
    <DataTemplate DataType="{x:Type local:TabItemDetail}">
        <TabItem Header="{Binding Header}"/>
    </DataTemplate>
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="110"/>
        <ColumnDefinition Width="5"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <ListBox Grid.Column="0" ItemsSource="{Binding DataSource}" SelectedItem="{Binding SelectedDataSource}"/>

    <TabControl Grid.Column="2" local:MySampleAttachedProperty.Header="{Binding SelectedDataSource}">
        <TabItem Header ="Connect" />
    </TabControl>
</Grid>

これがトリックを行う新しい添付プロパティクラスです

public class MySampleAttachedProperty
{
    public static string GetHeader(DependencyObject obj)
    {
        return (string)obj.GetValue(HeaderProperty);
    }

    public static void SetHeader(DependencyObject obj, string value)
    {
        obj.SetValue(HeaderProperty, value);
    }

    // Using a DependencyProperty as the backing store for Header.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty HeaderProperty =
        DependencyProperty.RegisterAttached("Header", typeof(string), typeof(MySampleAttachedProperty), new UIPropertyMetadata(CallBack));


    private static void CallBack(object sender, DependencyPropertyChangedEventArgs args)
    {
        TabControl tabControl = sender as TabControl;
        TabItem newTab = new TabItem { Header = args.NewValue };
        tabControl.Items.Add(newTab);
        newTab.Focus();
    }
}
于 2012-09-21T06:14:03.400 に答える