2016-10-10 15 views
1

現在、Xamarin.Formsアプリケーションで連絡先情報を表示するページを再設計しています。ページには、アイコンと関連情報を持つセクション(アドレス、電話番号、電子メールアドレスなど)のリストが表示されます。セクションは1行で区切られていなければなりませんが、最初の行の上と最後のセクションの下に行はありません。また、空のセクションはまったく表示されません。Xamarin.Forms:CSSの最後の型セレクタに相当

<ScrollView> 
    <StackLayout> 
    <Label Text="{Binding Contact.Name}" /> 
    <controls:ContactSection Icon="address.png"> 
     <!-- address-type stuff --> 
    </controls:ContactSection> 
    <controls:ContactSection Icon="phone.png"> 
     <!-- phone numbers --> 
    </controls:ContactSection> 
    <!-- further sections --> 
    </StackLayout> 
</ScrollView> 

私はそれがラインを除き、ほとんどの部分のために働いてガット:

マークアップは次のように基本的に見えます。 (BoxViewにはHeightRequestを1つだけ使用します)。正しく動作させるために、レンダラに最後のものを除くすべての可視セクションの下に線を引くように指示する必要があります。本質的には、私はCSS3スタイルの:not(:last-of-type)セレクタ(または上記の行に:not(:first-of-type))が必要です。

XAMLでこれを行う最善の方法は何ですか? (または、必要に応じてコードビハインドで)

+0

これは痛感です。かつて私が所有していたアイテムコンテナにブール値のFirstItem/LastItem添付プロパティを設定したListBoxサブクラスを書きました。 StackPanelのChildrenと同じ動作をすることができると思います。いったんこれを取得すれば、LastItemプロパティにトリガを持つスタイルを簡単に記述できます。 –

答えて

1

私はちょうど私がこれをしたいと思っていることを思い出したので、私は1つを書きました(スニペットでは10分の仕事です)。どのように/これがXamarinで動作するかを教えてください。私はそれでテストすることができません。

更新:今日は半分眠っていなければなりません。私は "StackPanel"として "StackLayout"を読んでいます。 OPはそれをXamarinに適合させ、そのコードを別の回答として掲示した。

using System; 
using System.Windows; 
using System.Windows.Controls; 

namespace HollowEarth.AttachedProperties 
{ 
    public static class PanelBehaviors 
    { 
     public static void UpdateChildFirstLastProperties(Panel panel) 
     { 
      for (int i = 0; i < panel.Children.Count; ++i) 
      { 
       var child = panel.Children[i]; 

       SetIsFirstChild(child, i == 0); 
       SetIsLastChild(child, i == panel.Children.Count - 1); 
      } 
     } 

     #region PanelExtensions.IdentifyFirstAndLastChild Attached Property 
     public static bool GetIdentifyFirstAndLastChild(Panel panel) 
     { 
      return (bool)panel.GetValue(IdentifyFirstAndLastChildProperty); 
     } 

     public static void SetIdentifyFirstAndLastChild(Panel panel, bool value) 
     { 
      panel.SetValue(IdentifyFirstAndLastChildProperty, value); 
     } 

     /// <summary> 
     /// Behavior which causes the Panel to identify its first and last children with attached properties. 
     /// </summary> 
     public static readonly DependencyProperty IdentifyFirstAndLastChildProperty = 
      DependencyProperty.RegisterAttached("IdentifyFirstAndLastChild", typeof(bool), typeof(PanelBehaviors), 
       // Default MUST be false, or else True won't be a change in 
       // the property value, so PropertyChanged callback won't be 
       // called, and nothing will happen. 
       new PropertyMetadata(false, IdentifyFirstAndLastChild_PropertyChanged)); 

     private static void IdentifyFirstAndLastChild_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      Panel panel = (Panel)d; 

      ((Panel)d).LayoutUpdated += (s, e2) => UpdateChildFirstLastProperties(panel); 
     } 

     #endregion PanelExtensions.IdentifyFirstAndLastChild Attached Property 

     #region PanelExtensions.IsFirstChild Attached Property 
     public static bool GetIsFirstChild(UIElement obj) 
     { 
      return (bool)obj.GetValue(IsFirstChildProperty); 
     } 

     public static void SetIsFirstChild(UIElement obj, bool value) 
     { 
      obj.SetValue(IsFirstChildProperty, value); 
     } 

     /// <summary> 
     /// True if UIElement is first child of a Panel 
     /// </summary> 
     public static readonly DependencyProperty IsFirstChildProperty = 
      DependencyProperty.RegisterAttached("IsFirstChild", typeof(bool), typeof(PanelBehaviors), 
       new PropertyMetadata(false)); 
     #endregion PanelExtensions.IsFirstChild Attached Property 

     #region PanelExtensions.IsLastChild Attached Property 
     public static bool GetIsLastChild(UIElement obj) 
     { 
      return (bool)obj.GetValue(IsLastChildProperty); 
     } 

     public static void SetIsLastChild(UIElement obj, bool value) 
     { 
      obj.SetValue(IsLastChildProperty, value); 
     } 

     /// <summary> 
     /// True if UIElement is last child of a Panel 
     /// </summary> 
     public static readonly DependencyProperty IsLastChildProperty = 
      DependencyProperty.RegisterAttached("IsLastChild", typeof(bool), typeof(PanelBehaviors), 
       new PropertyMetadata(false)); 
     #endregion PanelExtensions.IsLastChild Attached Property 
    } 
} 

使用例:

<StackPanel 
    xmlns:heap="clr-namespace:HollowEarth.AttachedProperties" 
    heap:PanelBehaviors.IdentifyFirstAndLastChild="True" 
    HorizontalAlignment="Left" 
    Orientation="Vertical" 
    > 
    <StackPanel.Resources> 
     <Style TargetType="Label"> 
      <Setter Property="Content" Value="Blah blah" /> 
      <Setter Property="Background" Value="SlateGray" /> 
      <Setter Property="Margin" Value="4" /> 

      <Style.Triggers> 
       <Trigger Property="heap:PanelBehaviors.IsFirstChild" Value="True"> 
        <Setter Property="Background" Value="DeepSkyBlue" /> 
        <Setter Property="Content" Value="First Child" /> 
       </Trigger> 
       <Trigger Property="heap:PanelBehaviors.IsLastChild" Value="True"> 
        <Setter Property="Background" Value="SeaGreen" /> 
        <Setter Property="Content" Value="Last Child" /> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
    </StackPanel.Resources> 
    <Label /> 
    <Label /> 
    <Label /> 
    <Label /> 
</StackPanel> 
+0

ありがとうございました!あなたのコードのXamarinバージョンを完全性のための私自身の答えとして追加しますが、あなたのものは確かに "正しい"ものです。 –

+0

@TimOkrongliそれは素晴らしいです。そしてXamarinのバージョンを投稿してくれてありがとう。 –

1

エド・プランケットは、私は彼のコードから構築された同等のXamarin.Formsを投稿することを決めたWPFのためのソリューションを供給した後。

namespace Foo.Behaviors 
{ 
    using System.Linq; 

    using Xamarin.Forms; 

    /// <summary> 
    ///  Identifies the first and last child of a <see cref="Layout{View}"/>. 
    /// </summary> 
    public class FirstAndLastChildBehavior 
    { 
     /// <summary> 
     ///  Identifies the first and last child of the given <see cref="Layout{View}"/>. 
     /// </summary> 
     /// <param name="layout">The <see cref="Layout{View}"/>.</param> 
     public static void UpdateChildFirstLastProperties(Layout<View> layout) 
     { 
      // This is just here to provide a convenient place to do filtering, e.g. .Where(v => v.IsVisible). 
      var children = layout.Children; 

      for (var i = 0; i < children.Length; ++i) 
      { 
       var child = children[i]; 

       SetIsFirstChild(child, i == 0); 
       SetIsLastChild(child, i == children.Length - 1); 
      } 
     } 

     #region PanelExtensions.IdentifyFirstAndLastChild Attached Property 
     /// <summary> 
     ///  Gets a value that controls whether the child-identifying functionality is enabled for the given <see cref="Layout{View}"/>. 
     /// </summary> 
     /// <param name="layout">The <see cref="Layout{View}"/>.</param> 
     /// <returns><c>True</c> if functionality has been enabled, <c>false</c> otherwise.</returns> 
     public static bool GetIdentifyFirstAndLastChild(Layout<View> layout) 
     { 
      return (bool)layout.GetValue(IdentifyFirstAndLastChildProperty); 
     } 

     /// <summary> 
     ///  Sets a value that controls whether the child-identifying functionality is enabled for the given <see cref="Layout{View}"/>. 
     /// </summary> 
     /// <param name="layout">The <see cref="Layout{View}"/>.</param> 
     /// <param name="value">The value.</param> 
     public static void SetIdentifyFirstAndLastChild(Layout<View> layout, bool value) 
     { 
      layout.SetValue(IdentifyFirstAndLastChildProperty, value); 
     } 

     /// <summary> 
     ///  Identifies the <see cref="IdentifyFirstAndLastChild"/> property. 
     /// </summary> 
     /// <remarks> 
     ///  The behavior can't be turned off; once the value is set to <c>true</c> the behavior will stick even if it's set back to 
     ///  <c>false</c> later. 
     /// </remarks> 
     public static readonly BindableProperty IdentifyFirstAndLastChildProperty = BindableProperty.CreateAttached(
      "IdentifyFirstAndLastChild", 
      typeof(bool), 
      typeof(FirstAndLastChildBehavior), 
      false, 
      BindingMode.OneWay, 
      null, 
      IdentifyFirstAndLastChildPropertyChanged); 

     /// <summary> 
     ///  Gets called when IdentifyFirstAndLastChildProperty changes. 
     /// </summary> 
     /// <param name="bindable">The object we're bound to.</param> 
     /// <param name="oldValue">This parameter is not used.</param> 
     /// <param name="newValue">This parameter is not used.</param> 
     private static void IdentifyFirstAndLastChildPropertyChanged(BindableObject bindable, object oldValue, object newValue) 
     { 
      var layout = (Layout<View>)bindable; 

      ((Layout<View>)bindable).LayoutChanged += (a, b) => UpdateChildFirstLastProperties(layout); 
     } 
     #endregion PanelExtensions.IdentifyFirstAndLastChild Attached Property 

     #region PanelExtensions.IsFirstChild Attached Property 
     /// <summary> 
     ///  Gets a value that determines whether the given <see cref="View"/> is the first child of its parent. 
     /// </summary> 
     /// <param name="obj">The <see cref="View"/>.</param> 
     /// <returns><c>True</c> if the <see cref="View"/> is the first child, <c>false</c> otherwise.</returns> 
     public static bool GetIsFirstChild(View obj) 
     { 
      return (bool)obj.GetValue(IsFirstChildProperty); 
     } 

     /// <summary> 
     ///  Sets a value that determines whether the given <see cref="View"/> is the first child of its parent. 
     /// </summary> 
     /// <param name="obj">The <see cref="View"/>.</param> 
     /// <param name="value">The value.</param> 
     public static void SetIsFirstChild(View obj, bool value) 
     { 
      obj.SetValue(IsFirstChildProperty, value); 
     } 

     /// <summary> 
     ///  Identifies the <see cref="IsFirstChild"/> property. 
     /// </summary> 
     public static readonly BindableProperty IsFirstChildProperty = BindableProperty.CreateAttached(
      "IsFirstChild", 
      typeof(bool), 
      typeof(FirstAndLastChildBehavior), 
      false); 
     #endregion PanelExtensions.IsFirstChild Attached Property 

     #region PanelExtensions.IsLastChild Attached Property 
     /// <summary> 
     ///  Gets a value that determines whether the given <see cref="View"/> is the last child of its parent. 
     /// </summary> 
     /// <param name="obj">The <see cref="View"/>.</param> 
     /// <returns><c>True</c> if the <see cref="View"/> is the last child, <c>false</c> otherwise.</returns> 
     public static bool GetIsLastChild(View obj) 
     { 
      return (bool)obj.GetValue(IsLastChildProperty); 
     } 

     /// <summary> 
     ///  Sets a value that determines whether the given <see cref="View"/> is the last child of its parent. 
     /// </summary> 
     /// <param name="obj">The <see cref="View"/>.</param> 
     /// <param name="value">The value.</param> 
     public static void SetIsLastChild(View obj, bool value) 
     { 
      obj.SetValue(IsLastChildProperty, value); 
     } 

     /// <summary> 
     ///  Identifies the <see cref="IsLastChild"/> property. 
     /// </summary> 
     public static readonly BindableProperty IsLastChildProperty = BindableProperty.CreateAttached(
      "IsLastChild", 
      typeof(bool), 
      typeof(FirstAndLastChildBehavior), 
      false); 
     #endregion PanelExtensions.IsLastChild Attached Property 
    } 
} 
関連する問題