These fields are calculated by you so the don't, in any real sense, exist for the user. What you need to do is reuse those values in your case statement.
CREATE PROCEDURE dbo.uspSelectTopicsForEdit
@SortDirection varchar(20)
as
select TopicID,TopicAddress,
(select sum(TopicViewNum) from TopicViews where TopicViews.TopicID=Topics.TopicID) as TopicViews,
(select count(Favorites.UserID) from Favorites where Favorites.TopicID=Topics.TopicID)as BookMarks
from Topics
ORDER BY
CASE @SortDirection
WHEN 'MostViewed' THEN (select sum(TopicViewNum) from TopicViews where TopicViews.TopicID=Topics.TopicID)
WHEN 'MostBookMarked' THEN (select count(Favorites.UserID) from Favorites where Favorites.TopicID=Topics.TopicID)
WHEN 'Oldest' THEN Topics.TopicID
END
In a situation like this, I would far prefer to use a stored function or handle the sorting on the client side if it's an appropriate business requirement, but this should get you going.
Why do I say handle the sorting at the client side? Well, if the user can change the sort direction, then your sample here requires you to go to the database again (which could return you different results). If you are sorting an in memory collection, then it's one less roundtrip you have to perform. There are caveats, of course, if you were performing paging then you'd want to do this at the server end, but you aren't doing the paging here so it's not an issue.