4

同じ列に異なるコントロール (現時点ではテキスト ボックスとコンボ ボックス) を表示できる WinForms または WPF グリッドを探しています。行 (ノード) 間の階層が表示されるように、ツリーリスト/ツリービュー機能も備えている必要があります。実行時にコントロールをセルに追加し、行の高さと列の幅をプログラムで変更できるようにする必要があります。
私はしばらく探していましたが、今のところ運がありません。助言がありますか?助けていただければ幸いです。

4

3 に答える 3

3

この回答の結果。

ここに画像の説明を入力

私は標準の WPF DataGrid を使用します。まだお金を支払う必要はありません。テンプレート列を選択して、その中で少しデータ バインディングを行うだけです。以下の例には、グリッドにバインドしている非常に単純なクラスがあります。 .

public class ListItemType
{
    public int Type { get; set; }
    public string Text { get; set; }
}

このクラスは明らかに何でもかまいませんが、この例ではタイプを 1 または 2 に設定しています。バインドされたリスト内のタイプが 1 のオブジェクトにはそれを表すボタンが与えられ、Type=2 のオブジェクトにはすべてそれを表す CheckBox。

データグリッドの XAML は次のようになります。(インデント++)

<DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False" Height="200" HorizontalAlignment="Left" Margin="10,10,0,0" Name="dataGrid1" VerticalAlignment="Top" Width="200" >
    <DataGrid.Columns>

        <!-- The template coloumn -->
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>

                    <!-- Each cell is put in to a content presenter so I can change it's content -->
                    <ContentPresenter>
                        <ContentPresenter.Content>
                            <Binding Path="Type">
                                <Binding.Converter>
                                    <local:SwitchConverter>

                                        <local:SwitchConverterCase When="1">
                                            <Button Content="{Binding Text}"></Button>
                                        </local:SwitchConverterCase>

                                        <local:SwitchConverterCase When="2">
                                            <CheckBox Content="{Binding Text}" />
                                        </local:SwitchConverterCase>


                                    </local:SwitchConverter>
                                </Binding.Converter>
                            </Binding>
                        </ContentPresenter.Content>
                    </ContentPresenter>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

上で使用したスイッチ コンバーターは、XAML コードを少し単純化する汎用コンバーターにすぎません。任意のコンバーターを使用できますが、とにかく使用したコンバーターのコードを次に示します。

/// <summary>
/// A converter that accepts <see cref="SwitchConverterCase"/>s and converts them to the 
/// Then property of the case.
/// </summary>
[ContentProperty("Cases")]
public class SwitchConverter : IValueConverter
{
    // Converter instances.
    List<SwitchConverterCase> _cases;

    #region Public Properties.
    /// <summary>
    /// Gets or sets an array of <see cref="SwitchConverterCase"/>s that this converter can use to produde values from.
    /// </summary>
    public List<SwitchConverterCase> Cases { get { return _cases; } set { _cases = value; } }
    #endregion
    #region Construction.
    /// <summary>
    /// Initializes a new instance of the <see cref="SwitchConverter"/> class.
    /// </summary>
    public SwitchConverter()
    {
        // Create the cases array.
        _cases = new List<SwitchConverterCase>();
    }
    #endregion

    /// <summary>
    /// Converts a value.
    /// </summary>
    /// <param name="value">The value produced by the binding source.</param>
    /// <param name="targetType">The type of the binding target property.</param>
    /// <param name="parameter">The converter parameter to use.</param>
    /// <param name="culture">The culture to use in the converter.</param>
    /// <returns>
    /// A converted value. If the method returns null, the valid null value is used.
    /// </returns>
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        // This will be the results of the operation.
        object results = null;

        // I'm only willing to convert SwitchConverterCases in this converter and no nulls!
        if (value == null) throw new ArgumentNullException("value");

        // I need to find out if the case that matches this value actually exists in this converters cases collection.
        if (_cases != null && _cases.Count > 0)
            for (int i = 0; i < _cases.Count; i++)
            {
                // Get a reference to this case.
                SwitchConverterCase targetCase = _cases[i];

                // Check to see if the value is the cases When parameter.
                if (value == targetCase || value.ToString().ToUpper() == targetCase.When.ToString().ToUpper())
                {
                    // We've got what we want, the results can now be set to the Then property
                    // of the case we're on.
                    results = targetCase.Then;

                    // All done, get out of the loop.
                    break;
                }
            }

        // return the results.
        return results;
    }

    /// <summary>
    /// Converts a value.
    /// </summary>
    /// <param name="value">The value that is produced by the binding target.</param>
    /// <param name="targetType">The type to convert to.</param>
    /// <param name="parameter">The converter parameter to use.</param>
    /// <param name="culture">The culture to use in the converter.</param>
    /// <returns>
    /// A converted value. If the method returns null, the valid null value is used.
    /// </returns>
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

/// <summary>
/// Represents a case for a switch converter.
/// </summary>
[ContentProperty("Then")]
public class SwitchConverterCase
{
    // case instances.
    string _when;
    object _then;

    #region Public Properties.
    /// <summary>
    /// Gets or sets the condition of the case.
    /// </summary>
    public string When { get { return _when; } set { _when = value; } }
    /// <summary>
    /// Gets or sets the results of this case when run through a <see cref="SwitchConverter"/>
    /// </summary>
    public object Then { get { return _then; } set { _then = value; } }
    #endregion
    #region Construction.
    /// <summary>
    /// Switches the converter.
    /// </summary>
    public SwitchConverterCase()
    {
    }
    /// <summary>
    /// Initializes a new instance of the <see cref="SwitchConverterCase"/> class.
    /// </summary>
    /// <param name="when">The condition of the case.</param>
    /// <param name="then">The results of this case when run through a <see cref="SwitchConverter"/>.</param>
    public SwitchConverterCase(string when, object then)
    {
        // Hook up the instances.
        this._then = then;
        this._when = when;
    }
    #endregion

    /// <summary>
    /// Returns a <see cref="System.String"/> that represents this instance.
    /// </summary>
    /// <returns>
    /// A <see cref="System.String"/> that represents this instance.
    /// </returns>
    public override string ToString()
    {
        return string.Format("When={0}; Then={1}", When.ToString(), Then.ToString());
    }
}

最後に、必要なツリービューコンポーネントについて..実際には、各セル内に別のデータグリッドを配置して、必要なレベルの深さを実現できます。

于 2012-06-15T14:20:39.357 に答える
1

いくつかの巧妙なテンプレートを備えた標準の WPF TreeView がそのトリックを行うことがわかると思います

于 2012-06-15T14:32:14.613 に答える
0

そのようなコンポーネントにお金を払うことができるのであれば、Telerik コンポーネントを強くお勧めします。彼らは多くのコントロールを持っており、技術サポートは素晴らしいです.

いくつかの例を見て、それらの製品がニーズに合っているかどうかを確認できます。

WPF 用 Telerik GridView

WPF の Telerik TreeListView

于 2012-06-15T13:54:52.730 に答える