3

サイトマップがあるとしましょう

<mvcSiteMapNode title="Home" controller="Home" action="Index" changeFrequency="Always" >
        <mvcSiteMapNode title="Home" controller="Home" action="Index" visibility="MenuHelper,!*">
            <mvcSiteMapNode title="T1" controller="Home" action="T1" />
            <mvcSiteMapNode title="T2" controller="Home" action="T2"/>
        </mvcSiteMapNode>
        <mvcSiteMapNode title="Help" controller="Help" action="Index">
            <mvcSiteMapNode title="T1" controller="Help" action="T1" />
            <mvcSiteMapNode title="T2" controller="Help" action="T2" />
            <mvcSiteMapNode title="T3" controller="Help" action="T3" />
            <mvcSiteMapNode title="T4" controller="Help" action="T4" />
            <mvcSiteMapNode title="T5" controller="Help" action="T5" />
            <mvcSiteMapNode title="T6" controller="Help" action="T6" />
        </mvcSiteMapNode>
</mvcSiteMapNode>

@Html.MvcSiteMap().Menu()上記のノードに含まれるメニューが表示されますが、フッターに、サイトマップから特定のノードのみを表示したい、ノードを表示したいとしましょうHelp:

    <ul>
    <li>
    <a href="/help">
    </li>
    <li>
    <a href="/help/t1">T1</a>
    </li>
    <li>
    <a href="/help/t2">T2</a>
    </li>
    //and so on....
    </ul>

どうやってやるの?

カスタム テンプレートを作成する必要があるかもしれないと推測していますが、文字列値をカスタム テンプレートに渡すにはどうすればよいですか?

4

1 に答える 1

3

オプション1

これを行う 1 つの方法は、開始ノードを明示的に設定することです。まず、開始ノードに明示的なキーを与えます。

<mvcSiteMapNode title="Help" controller="Help" action="Index" key="HelpKey">
    <mvcSiteMapNode title="T1" controller="Help" action="T1" />
    <mvcSiteMapNode title="T2" controller="Help" action="T2" />
    <mvcSiteMapNode title="T3" controller="Help" action="T3" />
    <mvcSiteMapNode title="T4" controller="Help" action="T4" />
    <mvcSiteMapNode title="T5" controller="Help" action="T5" />
    <mvcSiteMapNode title="T6" controller="Help" action="T6" />
</mvcSiteMapNode>

メニューのオーバーロードを使用します。

@Html.MvcSiteMap().Menu(Html.MvcSiteMap().SiteMap.FindSiteMapNodeFromKey("HelpKey"), false, false)

しかし、そのようにすると、あまり制御できません。

オプション 2

カスタムの可視性プロバイダーを使用することもできます。sourceMetaData ディクショナリを使用して可視性プロバイダーにカスタム データを渡すことができるため、メニュー インスタンスごとに個別の「名前」を作成できます。

@Html.MvcSiteMap().Menu(new { name = "MainMenu" })
@Html.MvcSiteMap().Menu(new { name = "HelpMenu" })

次に、カスタムの可視性プロバイダーは、FilteredSiteMapNodeVisibilityProvider がカスタムの「name」プロパティに使用するのと同じロジックを使用できます。

/// <summary>
/// Filtered SiteMapNode Visibility Provider for use with named controls.
/// 
/// Rules are parsed left-to-right, first match wins. Asterisk can be used to match any control or any control name. Exclamation mark can be used to negate a match.
/// </summary>
public class CustomFilteredSiteMapNodeVisibilityProvider
    : SiteMapNodeVisibilityProviderBase
{
    #region ISiteMapNodeVisibilityProvider Members

    /// <summary>
    /// Determines whether the node is visible.
    /// </summary>
    /// <param name="node">The node.</param>
    /// <param name="sourceMetadata">The source metadata.</param>
    /// <returns>
    ///     <c>true</c> if the specified node is visible; otherwise, <c>false</c>.
    /// </returns>
    public override bool IsVisible(ISiteMapNode node, IDictionary<string, object> sourceMetadata)
    {
        // Is a visibility attribute specified?
        string visibility = string.Empty;
        if (node.Attributes.ContainsKey("visibility"))
        {
            visibility = node.Attributes["visibility"].GetType().Equals(typeof(string)) ? node.Attributes["visibility"].ToString() : string.Empty;
        }
        if (string.IsNullOrEmpty(visibility))
        {
            return true;
        }
        visibility = visibility.Trim();

        // Check for the source HtmlHelper
        if (sourceMetadata["HtmlHelper"] == null)
        {
            return true;
        }
        string htmlHelper = sourceMetadata["HtmlHelper"].ToString();
        htmlHelper = htmlHelper.Substring(htmlHelper.LastIndexOf(".") + 1);

        string name = sourceMetadata["name"].ToString();

        // All set. Now parse the visibility variable.
        foreach (string visibilityKeyword in visibility.Split(new[] { ',', ';' }))
        {
            if (visibilityKeyword == htmlHelper || visibilityKeyword == name || visibilityKeyword == "*")
            {
                return true;
            }
            else if (visibilityKeyword == "!" + htmlHelper || visibilityKeyword == "!" + name || visibilityKeyword == "!*")
            {
                return false;
            }
        }

        // Still nothing? Then it's OK!
        return true;
    }

    #endregion
}

次に、コントロール タイプの代わりに名前を使用するように構成を更新します。

<mvcSiteMapNode title="Home" controller="Home" action="Index" changeFrequency="Always" >
        <mvcSiteMapNode title="Home" controller="Home" action="Index" visibility="MainMenu,!*">
            <mvcSiteMapNode title="T1" controller="Home" action="T1" />
            <mvcSiteMapNode title="T2" controller="Home" action="T2"/>
        </mvcSiteMapNode>
        <mvcSiteMapNode title="Help" controller="Help" action="Index" visibility="HelpMenu,!*">
            <mvcSiteMapNode title="T1" controller="Help" action="T1" />
            <mvcSiteMapNode title="T2" controller="Help" action="T2" />
            <mvcSiteMapNode title="T3" controller="Help" action="T3" />
            <mvcSiteMapNode title="T4" controller="Help" action="T4" />
            <mvcSiteMapNode title="T5" controller="Help" action="T5" />
            <mvcSiteMapNode title="T6" controller="Help" action="T6" />
        </mvcSiteMapNode>
</mvcSiteMapNode>

また、構成でカスタム可視性プロバイダーをデフォルトとして設定することを忘れないでください。

内部 DI (web.config) の使用:

<appSettings>
    <add key="MvcSiteMapProvider_DefaultSiteMapNodeVisibiltyProvider" value="MyNamespace.CustomFilteredSiteMapNodeVisibilityProvider, MyAssemblyName"/>
</appSettings>

外部 DI の使用 (DI モジュール内 - Ninject の例を示す):

this.Kernel.Bind<ISiteMapNodeVisibilityProviderStrategy>().To<SiteMapNodeVisibilityProviderStrategy>()
    .WithConstructorArgument("defaultProviderName", "MyNamespace.CustomFilteredSiteMapNodeVisibilityProvider, MyAssemblyName");

注:親ノードの可視性をオフに切り替える必要があるが、子ノードは可視のままにする必要がある場合は、visibilityAffectsDescendants パラメーターを false に設定できるようにする Menu()、SiteMap()、または SiteMapPath() のオーバーロードのいずれかを使用する必要があります。デフォルトでは true です。

于 2013-10-29T18:43:50.783 に答える