Permanently Enabled Scrollbars Possible?
I am having a problem trying to come up with a way to keep ScrollBars/ScrollViewers
permanently enabled. I am working on a Data Entry application where certain users might only have "read" rights. This needs to disabled all controls so they are not able to make any changes.
When a control is disabled the user cannot view all information in scrollable controls (Infragistics XamDataGrid
, DevExpress GridControl
, TextBox
es with Wrap, ListBox
, etc). I was hoping I could "outsmart" Microsoft, and implement a Trigger
to set IsEnabled
to true when it was set to false, but of course, it didn't work (for a variety of reasons, I'm sure).
I've been focusing strictly on a textbox for now, to try to disabled the contents, but keep the ScrollViewer
enabled and have had no luck.
I was hoping there might be a solution, I.E. Overriding the IsEnabled
dependency property of the ScrollViewer
to always return true, or provide some sort of Style
that does not allow for the ScrollViewer
to become disabled.
I know a TextBox
has an IsReadOnly
property, but this is of no use for many of the other controls I need to resolve this issue for.
Is there any way I can go about solving this, in a fairly simple manner (simple as in that I can make a style that's applied everywhere, without changing the 200+ code files).
Thanks
EDIT: Here is the code I'm using in a sample project to try to resolve this issue.
<Window x:Class="WPFScrollViewerStyles.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true">
<ScrollViewer x:Name="PART_ContentHost" HorizontalScrollBarVisibility="Visible"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" IsEnabled="True" />
</Microsoft_Windows_Themes:ListBoxChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="IsEnabled" Value="True" TargetName="PART_ContentHost" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid IsEnabled="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="100" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<TextBox x:Name="txtScroller" Width="100" Height="100" AcceptsReturn="True" VerticalScrollBarVisibility="Auto" TextWrapping="Wrap" ScrollViewer.CanContentScroll="True">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras faucibus hendrerit lorem, auctor vehicula sem molestie nec. Quisque non massa quam. Nullam tempor blandit tempor. Integer in molestie ipsum. Donec augue mi, auctor vitae scelerisque a, vehicula ac ipsum. Etiam posuere vulputate augue quis convallis. Nullam aliquet purus nec lacus fermentum hendrerit egestas purus tincidunt. Suspendisse quis lacinia libero. Quisque facilisis turpis at augue dignissim aliquam ultrices sem porta. Etiam sagittis arcu id nibh ultrices dictum. Nulla non lectus luctus est malesuada luctus. Praesent sed lobortis nisi. Morbi et porttitor massa. Sed pellentesque, nisl eu imperdiet varius, ligula augue cursus nisl, eu egestas metus velit non elit. Phasellus elementum hendrerit risus, eu tincidunt ante gravida vel.
</TextBox>
<ListBox x:Name="lstScroller" Width="100" Height="100" Grid.Column="1">
<ListBox.Items>
<ListBoxItem Content="Item 1" />
<ListBoxItem Content="Item 2" />
开发者_高级运维 <ListBoxItem Content="Item 3" />
<ListBoxItem Content="Item 4" />
<ListBoxItem Content="Item 5" />
<ListBoxItem Content="Item 6" />
<ListBoxItem Content="Item 7" />
<ListBoxItem Content="Item 8" />
<ListBoxItem Content="Item 9" />
<ListBoxItem Content="Item 10" />
<ListBoxItem Content="Item 11" />
<ListBoxItem Content="Item 12" />
<ListBoxItem Content="Item 13" />
<ListBoxItem Content="Item 14" />
<ListBoxItem Content="Item 15" />
</ListBox.Items>
</ListBox>
</Grid>
Thanks to Cedric Dussud over at Microsoft, I have found a solution.
For reference: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/3bf5e186-845c-4b63-acd9-17d294a30f77
Rather than subclassing the ScrollViewer control, I override the Metadata in the Application_Startup event of the application, like so:
ScrollViewer.IsEnabledProperty.OverrideMetadata(typeof(ScrollViewer), new UIPropertyMetadata(true, new PropertyChangedCallback(ScrollViewer_IsEnabledPropertyChanged), new CoerceValueCallback(ScrollViewerForceEnabled)));
I then handle the CoerceValueCallback to always return true, like so:
private static void ScrollViewer_IsEnabledPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs args) { }
private static object ScrollViewerForceEnabled(DependencyObject source, object value)
{
return true;
}
According to Cedric, this might have unforeseen consequences, but as of now (and my all mighty test application with a disabled grid and two scrollable controls) I have not found one. Hopefully this solution can help someone else out, without problems.
I know this is an old question, but I think I found a similar but simpler solution which may help others: instead of overriding the propert metadata for the ScrollViewer's IsEnabledProperty, I applied excatly the same approach, but to the the ScrollBar's IsEnabledProperty. This seems to work okay and doesn't require me to create and apply a new template to the scroll-viewers. The only draw-back seems to be that the mouse-wheel and page-up/down keyboard commands do not work (since the scroll viewer itself is still disabled). The override metadata code is:
ScrollBar.IsEnabledProperty.OverrideMetadata(
typeof(ScrollBar),
new FrameworkPropertyMetadata(
(PropertyChangedCallback) null,
(CoerceValueCallback) AlwaysCoerceToTrue));
and the 'AlwaysCoerceToTrue' method is:
private static object AlwaysCoerceToTrue(DependencyObject o, object value)
{
return true;
}
I think you can restyle the UI elements, making them use a control template that includes
<ScrollViewer HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Visible" ... />
For example, for the TextBox
you can use a modified default control template:
<ControlTemplate TargetType="{x:Type TextBoxBase}">
<Border Name="Border" CornerRadius="2" Padding="2" BorderThickness="1">
...
<ScrollViewer Margin="0" x:Name="PART_ContentHost"
HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Visible"/> <!-- HERE -->
</Border>
</ControlTemplate>
精彩评论