2015-02-23 69 views
2

我有一個WPF用戶控件上的ScrollViewer,我想要實現的是在ScrollViewer的頂部和底部顯示陰影圖像,但隱藏頂部陰影滾動條位於頂部,並在滾動條位於底部時隱藏底部陰影。WPF - 滾動查看滾動查看器時設置圖像的可見性

換句話說,我需要以某種方式將圖像的Visibility屬性綁定到ScrollViewer的偏移量。下面的代碼顯然是不正確的,但應該說明我正在嘗試做什麼。

任何幫助將不勝感激。

<Grid> 
    <Image Source="Shadow.png" VerticalAlignment="Top"> 
     <Image.Resources> 
      <Style TargetType="Image"> 
       <Style.Triggers> 
        <Trigger SourceName="Scroller" Property="VerticalOffset" Value="GREATER THAN ZERO OR LESS THAN MAX"> 
         <Setter Property="Visibility" Value="Collapsed" /> 
        </Trigger> 
       </Style.Triggers> 
      </Style> 
     </Image.Resources> 
    </Image> 
    <ScrollViewer Height="200" x:Name="Scroller"> 
     <ContentControl /> 
    </ScrollViewer> 
</Grid> 
+0

我認爲這可能(至少部分)回答你的問題:http://stackoverflow.com/questions/10793717/how-to-find-that-scrollviewer-is-scrolled-to-the-end-in- wpf – thomasb 2015-02-23 16:48:02

回答

2

這是我會做的:

首先,你需要一個IMultiValueConverter:

public class ScrollOffsetToVisibilityConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (values == null) 
      throw new ArgumentException("Values cannot be null."); 
     if (values.Count() != 2) 
      throw new ArgumentException("Incorrect number of bindings (" + values.Count() + ")"); 
     if (parameter == null) 
      throw new ArgumentException("Parameter cannot be null."); 

     var top = parameter.ToString().ToUpper() == "TOP"; 

     var offset = Double.Parse(values[0].ToString()); 
     var maxHeight = Double.Parse(values[1].ToString()); 

     return (top && offset == 0) || (!top && offset == maxHeight) ? Visibility.Visible : Visibility.Collapsed; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

然後,您可以使用此轉換器應用二傳手的圖像的可見性屬性。

<Image.Style Source="Shadow.png" VerticalAlignment="Top"> 
    <Style> 
     <Setter Property="Image.Visibility"> 
      <Setter.Value> 
       <MultiBinding Converter="{StaticResource ScrollOffsetToVisibilityConverter}" ConverterParameter="Top"> 
        <Binding ElementName="Scroller" Path="VerticalOffset"/> 
        <Binding ElementName="Scroller" Path="ScrollableHeight"/> 
       </MultiBinding> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</Image.Style> 

只是通過在「頂部」或「底部」(或者更準確地說,不「頂部」)爲ConverterParameter返回「可見」,如果滾動條在頂部或底部。

+0

謝謝,這就像一個魅力。 – wwarby 2015-02-25 10:04:29

+0

這段代碼真的幫了我很大忙 - 但是我不得不在交換器代碼中交換Visible和Collapsed,因爲行爲與我想要的和我操縱的Grid元素相反。 – 2016-04-04 11:01:23

0

你必須使用ScrollBar而不是ScrollViewer因爲當它到達其內容的末尾ScrollViewer不能告訴。 (或者至少我還沒有看到這樣做的可靠方法)。另一方面ScrollBar更適合這些類型的操作。

我用一個ListBox與幾個項目來測試這種行爲。你可以改變它到任何你需要的。

的XAML:

<Grid> 
    <ListBox ScrollBar.Scroll="ListBox_Scroll"> 
     <!-- add many items here --> 
     <TextBlock Text="something"/> 
    </ListBox> 

    <Image Source="Shadow.png" VerticalAlignment="Top"> 
     <Image.Style> 
      <Style TargetType="Image"> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding ScrollerState}" 
          Value="{x:Static enum:ScrollState.AtTheTop}"> 
         <Setter Property="Visibility" Value="Collapsed" /> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Image.Style> 
    </Image> 
    <Image Source="Shadow.png" VerticalAlignment="Bottom"> 
     <Image.Style> 
      <Style TargetType="Image"> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding ScrollerState}" 
          Value="{x:Static enum:ScrollState.AtTheBottom}"> 
         <Setter Property="Visibility" Value="Collapsed" /> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Image.Style> 
    </Image> 
</Grid> 

正如你看到的,我改變了觸發DataTrigger和使用的DataContext一個綁定屬性(名爲ScrollerStateScrollState型這是一種簡單枚舉)結合。

枚舉:

public enum ScrollState 
{ 
    AtTheTop, AtTheBottom, InBetween 
} 

現在,在後面的代碼,我們實行的地方,我們改變ScrollerState值Scroll事件:

public MainWindow() 
{ 
    InitializeComponent(); 
    DataContext = new VM(); 
} 

private void ListBox_Scroll(object sender, ScrollEventArgs e) 
{ 
    ScrollBar sb = e.OriginalSource as ScrollBar; 

    if (sb.Orientation == Orientation.Horizontal) 
     return; 

    if (sb.Value == 0) 
     (DataContext as VM).ScrollerState = ScrollState.AtTheTop; 
    else if (sb.Value == sb.Maximum) 
     (DataContext as VM).ScrollerState = ScrollState.AtTheBottom; 
    else 
     (DataContext as VM).ScrollerState = ScrollState.InBetween; 
} 

VM(這方面的一個實例被設置爲在DataContext窗口):

public class VM : DependencyObject 
{ 
    public ScrollState ScrollerState 
    { 
     get { return (ScrollState)GetValue(ScrollerStateProperty); } 
     set { SetValue(ScrollerStateProperty, value); } 
    } 
    public static readonly DependencyProperty ScrollerStateProperty = 
     DependencyProperty.Register("ScrollerState", typeof(ScrollState), typeof(VM), 
     new PropertyMetadata(ScrollState.AtTheTop)); 
} 
+0

非常感謝,我敢肯定,這將工作 - 我採取了替代建議,因爲它不需要任何代碼。 – wwarby 2015-02-25 10:05:28